[Unity] Raycast(레이캐스트)

⭐ 레이캐스트란?

● 시작 지점부터 일직선상으로 해당하는 레이저를 발사하고, 레이저에 닿는 오브젝트를 검출하는 기능

● 레이어마스크(LayerMask)를 통해 검출하고 싶은 오브젝트를 지정 가능

● FPS 게임의 히트스캔, 오브젝트 선택, AI 탐지, 점프 기능의 땅 판정 등에 사용

 

 

● 캡슐 오브젝트(좌측)에서 레이를 쏘는 모습입니다. (코드는 아래에 나옵니다.)

● Gizmos를 통해 레이저를 시각적으로 볼 수 있습니다.

 

💡 Raycast 형식

if (Physics.Raycast(origin, direction, out RaycastHit hitInfo, maxDistance, layerMask))
{
    Debug.Log("Ray hit: " + hitInfo.collider.name);
}

//파라미터 설명
origin → 레이저를 쏘는 시작 위치
direction → 레이저가 향하는 방향
hitInfo → 검출된 물체의 정보를 담는 변수
maxDistance → 레이저의 최대 길이
layerMask → 특정 레이어만 검출하도록 제한

 

 

💡 RaycastHit로 알 수 있는 속성들

프로퍼티 설명
collider 충돌한 콜라이더 정보
point 충돌 지점의 월드 좌표
normal 충돌 표면의 법선 벡터
distance 레이저의 시작 지점으로부터의 거리
transform 충돌한 오브젝트의 트랜스폼
rigidbody 충돌한 오브젝트의 리지드바디

 

💡 비트 연산으로 LayerMask 설정하기

유니티의 레이어는 int 타입의 비트 플래그로 관리되며, 총 32개의 레이어를 만들 수 있습니다.

따라서 LayerMask.GetMask("레이어 이름")으로 충돌할 레이어를 설정할 수도 있지만

비트 연산으로 설정할 수도 있습니다.

또한 [SerializeField]를 이용해 직렬화로 인스펙터에서 레이어 마스크를 설정할 수도 있습니다.

//8번 레이어만 포함
int layerMask = 1 << 8

//1번, 7번 레이어만 포함
int layerMask = (1 << 1) | (1 << 7)

 

 

Raycast 사용법


● 조건에 맞는 하나의 물체를 검출할 때

//ray를 미리 만들어줌
Ray ray = new Ray(transform.position, transform.forward * 10f);

if (Physics.Raycast(ray, out RaycastHit hit, LayerMask.GetMask("Enemy")))
{
    Debug.Log($"{hit.collider.name} 충돌!");
}

 

transform.position의 위치에서 transform.forward 방향으로 10f 거리만큼 레이저를 쏴 "ENEMY" 레이어가 충돌되면

hit 변수에 담고 로그를 출력하는 코드입니다.

● 단 처음에 충돌한 물체만 검출하고 그 뒤의 물체들은 조건에 맞더라도 무시합니다.

 

 

 

● 조건에 맞는 다수의 물체를 검출할 때

//Physics.RaycastAll
Ray ray = new Ray(transform.position, transform.forward * 10f);
RaycastHit[] hits = Physics.RaycastAll(ray, LayerMask.GetMask("Enemy"));

if (hits.Length > 0)
{
    foreach (var hit in hits)
    {
        Debug.Log($"{hit.collider.name} 충돌!");
    }
}

//Physics.RaycastNonAlloc
RaycastHit[] hits = new RaycastHit[10];
Ray ray = new Ray(transform.position, transform.forward * 10f);

Physics.RaycastNonAlloc(ray, hits, LayerMask.GetMask("ENEMY"));

if(hits.Length > 0 )
{
    foreach(var hit in hits)
    {
        Debug.Log($"{hit.collider.name} 충돌!");
    }
}

● hits라는 RaycastHit 배열에 충돌하는 모든 물체를 담습니다.

● RaycastAll은 RaycastHit[] 타입을 반환합니다.

● RaycastNonAlloc은 int 타입을 반환합니다.

 

 

RaycastAll과 RaycastNonAlloc의 차이점

● RaycastAll: 탐지할 때마다 배열을 생성하지만 크기가 지정되어 있지 않아 크기에 제한이 없습니다.


● RaycastNonAlloc: 미리 생성된 배열을 받아와 값을 담지만 크기가 제한되어 있어 탐지체 개수가 배열의 크기보다 많으면 나머지 오브젝트는 버립니다.

 

 

 

 

다양한 모양의 Ray들

 

● SphereCast

SphereCast

//SphereCast 예시
Physics.SphereCast(transform.position, 0.5f, transform.forward, out RaycastHit hit, 10f, LayerMask.GetMask("ENEMY"));

 

 

 

 

● BoxCast

BoxCast

 

//BoxCast 예시
Physics.BoxCast(transform.position, new Vector3(0.5f, 0.5f, 0.5f), transform.forward, Quaternion.identity, 10f, LayerMask.GetMask("ENEMY"));

 

 

 

● CapsuleCast

CapsuleCast

//CapsuleCast 예시
Physics.CapsuleCast(transform.position, transform.position, 1f, transform.forward, 10f, LayerMask.GetMask("ENEMY"));