충돌 처리를 하게 된다면 Physics를 많이 쓰게 됩니다.
크게 나누게 된다면 Raycast 와 Overlap 계열, Cast 계열이 있습니다.
Raycast
한 점에서 직선 방향으로 빛을 쏴 지정된 거리까지 충돌하는 객체가 있는지 체크하는 용도로 쓰고 있습니다.
투사체가 어디에 충돌했는지, 혹은 바닥 높이가 몇인지 등등등 다방면으로 쓰이고 있습니다.
Overlap 계열
Physics.OverlapSphere를 보면 위와 같이 표시 됩니다.
Overlap 에서 가장 큰 특징은 충돌한 Collider를 반환 하게 됩니다.
정확히 이야기 하자면 내가 누구와 충돌했는지를 체크하게 됩니다.
Alloc버전과 NonAlloc버전이 있는데 Alloc버전은 Collider배열을 반환합니다.
NonAlloc버전은 Collider배열을 매개변수로 받으며 충돌한 객체의 수를 int로 반환 받습니다.
메모리 관리적 측면에서 NonAlloc이 대부분 좋은 선택이지만 Alloc버전도 엄청난 문제가 있지는 않습니다.
Cast 계열
파라미터 구조가 약간 다른데 RaycastHit 가 들어가고 있습니다.
Overlap과 가장 큰 특징이 이것인데 Overlap이 누구와 충돌했는지 라면 Cast는 어디에 충돌 했는지 입니다.
RaycastHit 구조체에는 point변수가 있어서 어디에 충돌했는지, distance가 있어서 검사의 중심점과 얼마나 떨어져 있는 지 등등을 쉽게 알 수 있습니다.
또한 distance항목이 있어서 정해진 위치 뿐만 아니라 범위까지 포함할 수 있습니다.
Cube를 기준으로 스피어 A와 B가 있다고 했을때 입니다.
RaycastHit[] hitInfo = new RaycastHit[2];
int hitCount = Physics.SphereCastNonAlloc(transform.position, 1f, transform.forward, hitInfo, 1f);
for (int i = 0; i < hitCount; ++i)
{
Debug.Log(hitInfo[i].collider.gameObject.name);
}
maxDistance를 1로만 했을경우
SphereA만 검출되고 있습니다.
maxDistance를 5로 했을경우 둘다 검출 됩니다.
시작지점을 기준으로 객체모양(위의 코드는 Sphere)을 히트체크하고 direction 방향으로 maxDistance까지 움직이는동안 중간에 걸리는 모든 것들도 같이 체크 합니다.
Sphere로 했을경우 캡슐같은 효과가 나게 됩니다.
물론 maxDistance를 0으로 하면 제자리만 검출합니다.
overlap 과 cast모두 객체의 형태별(Box, Capsule, Sphere)로 있으며 Alloc버전과 NonAlloc버전이 있습니다.
필요에 의해서 나누어 쓰면 됩니다.
Layer의 경우 Physics 연산할때 불필요한 계산을 줄여주는 중요한 용도 입니다.
위의 상황에서 SphereA는 LayerA에 SphereB는 LayerB에 추가 하였습니다.
그리고 레이어 관련 항목을 코드에 추가 합니다.
RaycastHit[] hitInfo = new RaycastHit[2];
LayerMask layerMask = 1<<LayerMask.NameToLayer("LayerA");
int hitCount = Physics.SphereCastNonAlloc(transform.position, 1f, transform.forward, hitInfo, 5f, layerMask);
for (int i = 0; i < hitCount; ++i)
{
Debug.Log(hitInfo[i].collider.gameObject.name);
}
동일하게 maxDistance가 5이지만 SphereA만 검출 됩니다.
이렇게 레이어가 정해져 있다면 Physics연산에서 아예 제외 될 수 있기 때문에 불필요한연산을 많이 줄일 수 있습니다.
또한 중요한 사용법중 하나로 투사체에서의 처리 입니다.
총알같은 투사체는 매우 빠른 속도를 지니고 있기 때문에 Raycast로 연산을 하게 되는데 이때 투사체가 지니는 몇가지 특성은 다음과 같습니다.
- 벽과 충돌해야 한다.
- 바닥과 충돌해야 한다.
- 적팀과 충돌해야 한다.
- 아군팀과 충돌하면 안된다.
- 충돌 이후 소멸되어야 한다.
충돌이후 소멸되어야 한다는 특성 때문에 Raycast를 1번만 연산 해야 하며 이는 다음과 같이 풀이 할 수 있습니다.
- 벽, 바닥, 적팀의 레이어로 묶는다.
- 정리된 레이어로 Raycast를 한다.
- 충돌이 감지 되었다면 RaycastHit객체 기준으로 충돌이 감지된 객체를 판단 한다.
위와 같이 처리한다면 투사체 처리를 비교적 간편하게 줄일 수 있을 것 같습니다.
물론 충돌된 객체를 판단하는 과정이 남았지만 Tag를 주요객체에 잘 정리해서 달았거나 특정 컴퍼넌트가 있다면 TryGetComponent등으로 처리 할 수 있을 것입니다.
여기서 Physics.Raycast를 쓰는 이유는 1회만 충돌하게 되며 RaycastAll 이나 RaycastNonAlloc은 여러번 충돌을 검출 할 수 있기 때문에 1회 충돌체크해야 하는 지금 상황에 적절치 못하다고 생각 되었습니다.
'Unity Engine' 카테고리의 다른 글
유용한 공식 - 직선에 대한 한 점의 직각 좌표 구하기 (0) | 2022.11.10 |
---|---|
[Unity]CollisionFlag - CharacterController (0) | 2022.11.06 |
Behavior Tree - AI 이동 디테일 (0) | 2022.07.10 |
Behavior Tree - Custom Action (0) | 2022.07.07 |
Behavior Tree - Node Canvas (2) (0) | 2022.07.02 |