Trigger와 Collision을 자유 자재로 다룰 수 있다.
1. UnityEngine의 Collider와 Collision에 대해 컴포넌트 기본 구성을 이해한다.
2. ECS DOTS 1.0 기반의 물리 충돌은 ITriggerEventJob 혹은 ICollisionEventJob을 활용한다.
1. UnityEngine의 물리관련 컴포넌트 정리 [Collider , RigidBody]
2. 자주 쓰거나 중요한 팁과 관련된 정보 정리
3. ECS와 기존 컴포넌트 구성과 비교
4. ECS 스크립트 예제
0이면 중력의 영향을 받지 않는다. 그 외에는 영향을 받는다.
충돌 효과를 없앨 수 있다. Trigger 는 가능.
캐릭터의 움직임을 상황에 맞게 보간하는 기능
-interpolate : 이전 프레임을 근거로 다음 프레임을 보간.
-exterpolate : 다음 프레임을 근거로 이전 프레임을 보간.
ex. 콜라이더 벽을 뚫는 현상을 완화 하기 위해서는 exterpolate가 더 낫다.
-Discrete : 기본값, 모든 충돌 감지
-Continuous : 배경 감지 / ContinuousDynamic : 동적 감지 ( 일반과 배경감지를 번갈아 탐지 , 정밀함)
위치나 회전 값을 고정시킬 수 있는 기능.
트리거 감지 기능 스위치 : OnTriggerEvent
PolygonCollider 사용.
특정 힘 이상을 가하면 부러지는 효과를 표현할때 사용.
스프링 효과, 감속 비율, 최대 최소 거리, 브레이크 포스 등을 설정할 수 있음.
축을 기준으로 원 운동을 하는 효과 (경첩, 모터 등)
Ragdoll , 캐릭터 관절 효과를 표현할 수 있음.
커스텀 조인트, 모든 기능 내포, 상세 설정 가능.
ProjectSetting => Physics / Physics2D => 콜라이더 관계 체크
Trigger 나 Collision의 Stay이벤트에서는 IEnumerator를 사용할 수 있다. - 제어가능
private IEnumerator OnTriggerStay(Collide col) { ... }
동적, 키네마틱, 정적 타입.
기존 리지드 바디의 'CollisionDetection'과 대응
감속을 나타내는 프로퍼티, friction과 대응
3D를 타깃으로 만들어져 있다고 하지만, 2D에서 사용해도 괜찮음. 기존의 박스콜라이더, 서클콜라이더 모양 고르는 부분
둥근 모서리 너비, 각진 모서리를 둥글게 처리해 박스콜라이더와 스피어콜라이더를 둘다 타협해서 활용할 수 있음.
Create => DOTS => Physics 에 템플릿을 만들 수 있으니 참고.
Trigger 이벤트와 Collision 이벤트를 분리할 수 있음. 개별처리 쌍방처리 모두 가능.
충돌 태그 카테고리, 아래 Advanced는 MaterialTemplate과 연관이 있다.
BelongsTo : 현재 속한 태그 ( 내 태그 )
CollideWith : 반응 대상 태그 ( 상대방 태그 )
CustomTags : 머터리얼 관련 태그
5.1 이전 포스팅 기준으로 이어서 만들었다.
5.2 총알을 발사하고, 아이템을 만들어 생성된 오브젝트를 파괴하여 점수를 획득하는 로직을 구현하였다.
5.3 추가한 스크립트는 '충돌처리 이벤트 스크립트'와 '점수 스크립트' 둘이다.
5.4 ISystem이나 SystemBase나 둘다 가능하지만 이번에는 SystemBase로 만들었다.
ex. 충돌 이벤트 시스템
[UpdateInGroup(typeof(PhysicsSystemGroup))]
[UpdateAfter(typeof(EndSimulationEntityCommandBufferSystem))]
[BurstComplie]
public partial struct BulletColliderSystem : SystemBase
{
[BurstCompile]
protected override void OnUpdate()
{
// 이벤트 주체와 이벤트 대상을 찾는다.
var enemies = SystemAPI.QueryBuilder().WithAll<BallTag>().Build().ToEntityArray(Allocator.Persistent);
var weapons = SystemAPI.QueryBuilder().WithAll<BulletTag>().Build().ToEntityArray(Allocator.Persistent);
var ecb = SystemAPI.GetSingleton<EndFixedStepSimulationEntityCommandBufferSystem.Singleton>()
.CreateCommandBuffer(World.Unmanaged);
// 점수 스크립트
var pointEntity = SystemAPI.GetSingletonEntity<PointComponent>();
var pointComponent = SystemAPI.GetSingleton<PointComponent>();
// 충돌 처리를 잡 시스템에 위임
var bulletColliderEventJob= new BulletColliderEventJob
{
Enemies = enemies,
Weapons = weapons,
Ecb = ecb,
PointComponent = pointComponent,
Point = pointEntity
}.Schedule(SystemAPI.GetSingleton<SimulationSingleton>(), Dependency);
Debug.Log($"point : {pointComponent.Point}");
bulletColliderEventJob.Complete();
// 점수를 UI에 보낸다.
GameManager.Instance.UpdatePoint(pointComponent.Point);
}
}
[BurstCompile]
public partial struct WeaponColliderEventJob : ITriggerEventsJob
{
// 충돌 주체와 , 충돌 대상 배열
[ReadOnly] public NativeArray<Entity> Enemies;
[ReadOnly] public NativeArray<Entity> Weapons;
// 파괴 처리 버퍼
public EntityCommandBuffer Ecb;
// 점수
public PointComponent PointComponent;
public Entity Point;
public void Execute(TriggerEvent collisionEvent)
{
// 자기들 끼리 충돌이면 무시하고
if (InTheSameGroups(collisionEvent.EntityA, collisionEvent.EntityB))
return;
// 상대를 충돌하면 파괴하고 점수 올린 뒤, 점수 스크립트에 값을 할당한다.
if (Enemies.Contains(collisionEvent.EntityA) && Weapons.Contains(collisionEvent.EntityB))
{
Ecb.DestroyEntity(collisionEvent.EntityA);
PointComponent.Point++;
Ecb.SetComponent(Point,PointComponent);
Debug.Log($"[Collide] : entityA - ball - [{collisionEvent.EntityA} | entityB - bullet - [{collisionEvent.EntityB}]");
}
if (Weapons.Contains(collisionEvent.EntityA) && Enemies.Contains(collisionEvent.EntityB))
{
Ecb.DestroyEntity(collisionEvent.EntityB);
PointComponent.Point++;
Ecb.SetComponent(Point,PointComponent);
Debug.Log($"[Collide] : entityA - bullet - [{collisionEvent.EntityA} | entityB - ball - [{collisionEvent.EntityB}]");
}
}
// 자기들 끼리 충돌 되는 것을 방지하는 부분.
private bool InTheSameGroups(Entity entityA, Entity entityB)
{
return InTheSameGroup(Enemies, entityA, entityB) || InTheSameGroup(Weapons, entityA, entityB);
}
private bool InTheSameGroup(in NativeArray<Entity> group, Entity entityA, Entity entityB)
{
return group.Contains(entityA) && group.Contains(entityB);
}
}