지난번에 Raycast에 대한 기본을 정리하였습니다. 오늘은 단순한 선이 아닌 두께가 있는 도형을 쏘거나 범위내에 존재하는 Object를 판별하는 개념에 대하여 정리해보겠습니다.
Shapecast는 선이 아닌, 도형을 특정 방향으로 쏘아 경로상의 충돌을 찾는 방식을 의미합니다.
캡슐 형태의 캐릭터가 이동시 장애물을 미리 감지하거나 투사체의 두께를 고려한 충돌 판정이 발생할 때 주로 사용합니다.
기본적으로 Raycast의 hit와 동일한 구조체를 가지고 있습니다.
<style>
void SphereCastExample()
{
float radius = 2.0f; // 구체 반지름
float maxDistance = 10.0f;
Vector3 origin = transform.position;
Vector3 direction = transform.forward;
if(Physics.SphereCast(origin, radius, direction, out RaycastHit hit, maxDistance, m_hittableMask))
{
Debug.Log($"Sphere Hit {hit.collider.name}");
}
}
</style>
Overlap은 특정 궤적을 그리며 쏘는 것이 아닌 특정 시점에 해당 범위에 들어온 모든 물체를 배열로 반환하는 방식을 의미합니다.
폭발 범위 내 적이 있는지 판별하여 데미지를 가하거나 근접 공격 범위 내 적 탐지, 특정 구역 진입 확인시에 주로 사용합니다.
주요 특징으로 Overlap에 판별된 물체를 Collider[]배열로 반환하며 hit.point나 hit.normal과 같은 충돌 정보를 제공하지 않습니다.
<style>
void OverlapExample(Vector3 centerPostion)
{
Vector3 center = centerPostion;
float radius = 5.0f;
Collider[] hitColliders = Physics.OverlapSphere(center, radius);
foreach(var hitCollider in hitColliders)
{
Debug.Log($"Detected : {hitCollider.name}");
}
}
</style>
RaycastAll은 레이에 부딪힌 모든 충돌 정보를 담기 위해 매번 새로운 배열을 생성하여 반환합니다.
이 연산은 Update()함수처럼 프레임이 실행되면 수많은 가비지가 생성하여 스파이크 현상(화면 끊김)을 유발할 수 있습니다.
이를 해결하기위해 RaycastNonAlloc은 이미 만들어둔 배열을 재사용하여 새로운 메모리 할당을 발생시키지않아 스파이크 현상을 방지합니다.
RaycastNonAlloc은 충돌한 오브젝트의 리스트를 반환하는 것이 아닌 몇 개의 오브젝트가 부딪혔는지를 반환합니다.
예를 들어, 크기 3의 배열을 사전에 생성한 후 5개의 오브젝트가 부딪혔다면 가까운 순서대로 3개만 배열에 담고 2개는 무시하는 방식입니다.
<style>
void RaycastNonAllocExample()
{
Vector3 origin = transform.position;
Vector3 direction = transform.forward;
float maxDistance = 10.0f;
RaycastHit[] hitResults = new RaycastHit[5];
int hitCount = Physics.RaycastNonAlloc(origin, direction, hitResults, maxDistance);
for (int i = 0; i < hitCount; i++)
{
Debug.Log($"부딪힌 오브젝트: {hitResults[i].collider.name}");
}
}
</style>
RaycastNonAlloc의 핵심은 잦은 메모리 할당을 방지하기 위해 사전에 생성하는 만큼 개발상에서 충돌 갯수를 고려해 적절한 배열의 크기를 생성하는 것이라고 볼 수 있습니다.