내일배움캠프

내일배움캠프: 유니티 3D에서 Ray와 Raycast로 충돌 감지하기

pracumj 2024. 10. 30. 22:47

Ray란 ?

유니티에서 광선을 쏘는 방식으로 사용되며, 주로 물체간의 충돌을 감지하거나 특정 방향으로의 시야를 확인할 때 사용된다.

기본적으로 Ray는 원점에서 시작해 특정 방향으로 나아가는 선을 만들기위해 필요한 정보이다.  Raycast 함수를 통해 이 광선과 충돌하는 물체를 감지할 수 있다.

Ray 생성자

Ray ray = new Ray(Vector3 origin, Vector3 direction);​

 

 

Ray는 원점(origin)과 방향(direction)이라는 두 개의 프로퍼티로 이루어져 있으며, ray 객체를 생성할 때 원점과 방향을 인자로 전달하여 생성한다.

 

출처:https://docs.unity3d.com/ScriptReference/Ray.html

 


생성한 Ray를 사용해보자

  •  ray를 생성하는 것 만으로 충돌을 감지할 수 있으면 정말 좋겠지만, 이것만으로는 충돌을 감지할 수 없다. 이는 충돌을 감지하기 위한 준비과정이라고 생각하면 된다.
  • 이제 ray를 사용해 충돌을 감지하는 코드를 먼저 살펴 보자
private const float maxDistance = 1f;
public LayerMask detectLayerMask;

Ray ray = new Ray(transform.position, Vector3.forward);
RaycastHit hit;

// detectLayerMask에 해당하는 충돌을 감지
if (Physics.Raycast(ray, out hit, maxDistance, detectLayerMask))
{
    // hit를 사용해 충돌 처리
}

 

코드 살펴보기

주석에서 확인이 가능하듯이 실질적으로 충돌을 감지하는 로직의 주체는 Physics.Raycast다. 이 메서드는 다양한 오버로드가 있어, 원하는 매개변수를 조합해 사용이 가능하다.

 

기본적인 오버로딩 메서드 조합 

// 가장 기본적인 형태 , 원점에서 방향으로 ray를 발사해 충돌을 감지 
Physics.Raycast(Vector3 origin, Vector3 direction)

//충돌한 물체의 정보를 담을  RaycastHit hit를 추가한 형태
Physics.Raycast(Vector3 origin, Vector3 direction, out RaycastHit hit)

//최대 거리 설정
Physics.Raycast(Vector3 origin, Vector3 direction, out RaycastHit hit, float maxDistance )

//레이어 마스크 포함
Physics.Raycast(Vector3 origin, Vector3 direction, out RaycastHit hit,
float maxDistance, int layerMask);

//Ray 객체 사용
Physics.Raycast(Ray ray, out RaycastHit hit, float maxDistance, int layerMask);

 

이 외에도 필요한 인자를 조합하여 Raycast를 원하는 방향, 거리, 레이어 마스크, 트리거 옵션 등을 설정해 사용이 가능하다.

참고 링크: https://docs.unity3d.com/ScriptReference/Physics.Raycast.html 

 Physics.Raycast란? 실질적으로 충돌을 감지해주는 로직

  • 원점(origin)에서 지정된 방향으로 광선이 발사돼 경로 상에 있는 물체와의 충돌 여부를 검사하는 과정이다.
  • 기본적으로 Raycast는 가장 먼저 만나는 하나의 물체만 감지하기 때문에 모든 물체와의 충돌을 검사하고 싶다면 RaycastAll을 사용해야한다.
  • 기본적인 형태로 Raycast를 사용하면 충돌 여부에 따라 true , false 값만 반환된다.
  • 충돌정보를 저장하고 싶으면 out  RaycastHit hit 매개변수를 추가해줘야 한다. 이 경우, 충돌한 물체의 정보가 hit 객체 안에 저장되며, 충돌지점, 대상 물체의 정보등을 꺼내 쓸 수 있게된다.
  • 원하는 인자를 조합하여 방향,거리,레이어마스크, QueryTriggerInteraction 옵션 ( UseGlobal ,Ignore,Collide)등을 설정해 사용이 가능하다. 

Ray 객체는 꼭 필요한가?

  • Ray 객체가 없어도 문제 없다:  Raycast는 Ray 객체 없이도 origin과 direction을 직접 인자로 사용해 충돌을 감지할 수 있다. Ray 객체는 필수 요소가 아니라 편의를 위한 것!
  • Ray 객체를 사용하는 이유: Ray 객체를 사용하는 주된 이유는 반복 사용가독성 향상이다. 특정 원점과 방향으로 여러 번 Raycast를 해야 할 때, Ray 객체를 만들어 두면 코드가 간결해지고 관리가 편해질 수 있다. 또한, 원점과 방향이 복잡하게 정의된 경우 Ray 객체에 담아 사용하면 코드의 가독성이 좋아지는 결과를 얻을 수 있다 .

생성한 Ray를 씬에서 확인할 수 있을까?

Raycast에서 ray의 정보를 받아 충돌을 감지하는 경우 사실 눈으로는 ray가 잘 나가고 있는지 없는지 확인이 불가능하다. 하지만, 유니티에서는 친절하게도 Gizmos.DrawRay 메서드를 제공해 ray를 시각적으로도 확인이 가능하게 해준다.

코드예시

    void OnDrawGizmos() //debug(게임이 시작되지 않은 환경)에서도 기즈모를 씬뷰에 그려준다
    {
    	Ray ray = new Ray(transform.position,transform.forward * rayLength);
    
        Gizmos.color = Color.red;  // Ray 색상 설정       
        Gizmos.DrawRay(ray.origin, ray.direction); // Ray를 씬 뷰에서 시각적으로 표시
   }

 

해당 코드를 활용하면 씬 뷰에서 ray가 나아가는 모습을 시각적으로 확인이 가능하다. 만약 게임 시작전에 기즈모를 그리기 원하지 않는다면 OnDrawGizoms 대신 raycast를 적용하는 곳에서 사용해주면 된다!