LeeTaes 공부노트

[Unity] Raycast, LayerMask 본문

Game Programming/Unity Engine

[Unity] Raycast, LayerMask

리태s 2024. 7. 9. 17:23
728x90
반응형
개요

게임을 제작하다 보면 특정 방향에 물체가 있는지 판별해야 하는 경우가 생깁니다. 예를 들어 FPS 장르의 게임에서 총알의 궤적을 계산하거나, RTS 장르의 게임에서 클릭한 지점을 감지하는 등의 상황이 있습니다.

 

유니티(Unity)에서는 Raycast를 사용하여 특정 방향으로 광선을 쏘아 물체와의 충돌 여부를 감지할 수 있습니다.

이번에는 간단히 Raycast를 사용하는 방법에 대해 정리해보도록 하겠습니다.

Raycast

Raycast는 특정 지점(origin)에서 특정 방향(direction)으로 광선(ray)을 발사하며 해당 광선에 충돌된 물체에 대한 정보를 얻을 수 있는 기술입니다.

 

유니티(Unity)에서는 Physics.Raycast() 함수를 통해 다음과 같이 사용이 가능합니다.

Physics.Raycast(Vector3 origin, Vector3 direction, out RaycastHit hitInfo, float maxDistance, int layerMask);
  • origin : 광선을 발사할 시작 지점
  • direction : 광선이 발사되는 방향
  • hitInfo : 충돌 결과(정보)
  • maxDistance : 광선의 최대 진행 거리
  • layerMask : 충돌을 감지할 레이어 종류

Physics.Raycast() 함수의 반환형은 bool 타입으로, 충돌이 존재한다면 true, 아니라면 false를 반환합니다.

 

간단히 회전하는 Enemy를 만들어 지속적으로 전방을 탐지해보도록 하겠습니다.

 

Enemy Controller
void Update()
{
    // Enemy 회전
    transform.Rotate(0.0f, 3.0f, 0.0f);

    if (Physics.Raycast(transform.position, transform.forward, out RaycastHit hitInfo))
    {
        // 충돌한 물체의 이름 출력
        Debug.Log(hitInfo.collider.name);
        // Enemy로부터 충돌한 물체까지 라인 출력
        Debug.DrawLine(transform.position, hitInfo.point, Color.red, 0.5f);
    }
}

 

실행한 결과를 확인해보면 플레이어를 제대로 탐지하는 것을 확인할 수 있습니다.

 

위 상황에서 플레이어와 적 사이에 큰 벽이 추가되었다고 가정해봅시다.

 

Physics.Raycast()는 가장 먼저 충돌한 오브젝트만을 탐지하기 때문에 Player를 탐지하지 못 하고, 벽만 탐지하게 될 것입니다. (여러 물체를 탐지하고 싶은 경우 Physics.RaycastAll() 함수를 사용할 수 있습니다.)

결과를 확인해보면 다음과 같습니다.

 

여기서 Enemy는 벽을 탐지할 이유도 없으며, 만약 벽을 관통하여 플레이어를 탐지해야 한다면 LayerMask를 활용해 특정 레이어로 지정된 오브젝트만 탐지가 가능합니다.

LayerMask

LayerMask는 특정 레이어를 필터링하여 Raycast나 물리 계산을 할 때 유용하게 사용됩니다.

 

즉, 위와 같은 상황에서 LayerMask를 사용한다면 특정 레이어에 속한 물체(플레이어)를 대상으로 하여 Raycast를 수행할 수 있다는 이야기입니다.

 

유니티에서 LayerMask비트마스크를 사용하여 특정 레이어를 나타냅니다. 유니티의 레이어 시스템은 최대 32개의 레이어를 지원하며, 각 레이어는 0부터 31까지의 고유한 번호를 가집니다.

 

LayerMask는 이 번호를 비트마스크변환하여 사용합니다.

 

예를 들어, 1번과 2번 레이어의 물체를 탐지하고 싶은 경우 LayerMask는 다음과 같이 설정이 가능합니다.

private LayerMask LayerMask;

// 1번 레이어를 기존 비트와 or 연산 (0000 0000 | 0000 0010 = 0000 0010)
LayerMask |= (1 << 1);
// 2번 레이어를 기존 비트와 or 연산 (0000 0010 | 0000 0100 = 0000 0110)
LayerMask |= (1 << 2);

 

이제 위의 예시에서 LayerMask를 추가하여 Player만 탐지해보도록 하겠습니다.

 

우선 inspector 탭에서 Player 레이어를 추가해주고, 적용시켜주도록 하겠습니다.

레이어 추가
적용

코드에 LayerMask를 추가하고 테스트해주도록 합니다.

Enemy Controller
private LayerMask LayerMask;

void Start()
{
    // 특정 이름의 레이어(Player) 비트 켜기
    LayerMask |= (1 << LayerMask.NameToLayer("Player"));
}

void Update()
{
    transform.Rotate(0, 3, 0);
    
    if (Physics.Raycast(transform.position, transform.forward, out RaycastHit hitInfo, Mathf.Infinity, LayerMask))
    {
        Debug.Log(hitInfo.collider.name);
        Debug.DrawLine(transform.position, hitInfo.point, Color.red, 0.5f);
    }
}

 

결과를 확인해보면 이제 Wall은 탐지하지 않고, Player 레이어를 가진 플레이어만 탐지하는 것을 확인할 수 있습니다.

실행 결과

정리

유니티에서 Raycast는 게임 내 상호작용과 충돌 감지에 매우 유용한 기능입니다.

매우 간단한 예시만을 들었지만, 중요한 개념이므로 사용 방법을 확실히 알아둬야 한다고 생각합니다.

 

간단히 요약해보자면 다음과 같습니다.

  • Raycast : 특정 지점에서 특정 방향으로 광선을 쏘아 물체와의 충돌 여부를 감지하는 기술.
  • LayerMask : 특정 레이어를 필터링하여 Raycast나 물리 계산을 할 때 사용.

비트 마스크 연산이 어려울 수도 있으나, 비트의 각 위치를 사용해 여러 상태나 옵션을 표현한다고 생각하시고 자주는 아니지만 알아야 사용할 수 있는 개념이기에 필수적으로 이해하고 넘어가시기를 추천드립니다.

 

참고 자료

https://docs.unity3d.com/ScriptReference/Physics.Raycast.html

 

Unity - Scripting API: Physics.Raycast

Description Casts a ray, from point origin, in direction direction, of length maxDistance, against all colliders in the Scene. You may optionally provide a LayerMask, to filter out any Colliders you aren't interested in generating collisions with. Specifyi

docs.unity3d.com

https://docs.unity3d.com/kr/2022.2/Manual/use-layers.html

 

Unity에서 레이어 사용 - Unity 매뉴얼

레이어를 사용하여 프로젝트와 워크플로를 최적화할 수 있습니다. 레이어의 일반적인 용도에는 다음 사항이 포함됩니다. * 레이어 기반 렌더링 * 레이어 기반 충돌

docs.unity3d.com

 

728x90
반응형