Unity

RayCast 에 대해서 (RayCastHit2D)

박도치 2023. 12. 4. 17:51

유니티에서 Physics2D.RayCast는 씬에 직선을 투영하여 대상에 적중하면 true를 리턴하는 물리함수이다. RayCast함수를 이용하면 충돌에 관련된 정보 또는 RayCast를 통한 다양한 로직을 구현할 수 있다.

 

 

RayCast 함수 사용법 (3D)

 

Ray를 생성하여 Ray가 발사되고, Ray에 충돌한 정보를 얻어와 저장하는것이 기본적인 방법이다.

 

void RayReturn()
{
    Ray ray = new Ray(transform.position, transform.forward);
    RaycastHit rayHitData;

    Physics.Raycast(ray, out rayHitData);
}

 

Ray가 발사되고, Ray에 충돌한 정보를 rayHitData에 저장하게 된다.

 

위 Ray로 위치를잡고 발사하는것은 보통 3D에서 많이 쓰인다.

 

 

 

Raycast2D

 

3D와 2D의 차이는 알다시피 Z축이없다는 점이다. 그래서 Ray를 사용하지 않고, Vector2를 이용해서 Raycast가 출발할 좌표를 설정할 수 있다.

 

Physics2D.Raycast(Vector2 origin, Vector2 direction, float distance, int layerMask)

 

origin: Raycast가 출발할 좌표

direction: Raycast를 발사할 방향

distance: Raycast의 사거리

layerMast: Raycast가 감지할 레이어

 

etc

MinDepth는 지정한 Z좌표의 값보다 >= 크거나 같은 개체만 감지할수있게

MaxDepth는 지정한 Z좌표의 값보다 <= 작거나 같은 개체만 감지할수있게 

 

이런식으로 나눌 수 있다.

 

Raycast의 경우 Ray가 처음으로 충돌하는 객체만을 감지하며, 다른 모든 충돌은 무시하게 되지만, Ray를 쏴 모든 충돌 객체의 정보를 리스트로 반환하여 여러개를 불러오고 싶을 때에는 RaycastAll을 사용한다.

 

 

RaycastAll

RaycastHit2D[] hits = Physics2D.RaycastAll(origin, direction);
foreach (RaycastHit2D hit in hits) {
    // 각 충돌한 객체에 대한 처리
}

 

Raycast도 RaycastHit2D를 반환할 수 있지만, RayCastAll의 경우 Ray를 쏘는 선상의 모든 충돌체를 반환하다 보니 배열로 받게된다. 이를 foreach문을 이용해 충돌한 오브젝트에 대한 처리를 해줄 수 있다.

 

만약 일직선상의 모든것을 지우고싶다면 Vector2의 현재 오브젝트의 position을 찾아서 Ray로 정해주고 이를 원하는 거리만큼 쏴서 없애주면 된다.

 

그런데 일직선상에 모든것을 없애라고 해서 만약 없애기 싫은 충돌체와 없애고 싶은 충돌체가 겹쳐있다면 그 둘을 분간해줄수 있어야 하는데 이 때 필요한 것이 LayerMask 이다.

 

 

Tag와 같이 Layer를 지정해 줄 수 있다. 이는 inspector창에 있으며 객체들을 그룹화하고 그룹화된 정보로 다양한 기능을 제어할 수 있는 역할을 하는데 그 방법 중 하나이다.

 

Add Layer를 하여 자신이 원하는 Layer로 그룹화 한 후, 레이를 정해주고 위와같이 "Monster" 라는 Layer는 파괴하고 싶다고 정해주면 레이선상에서 Monster Layer를 가진 오브젝트들의 정보를 가져오고 필요한 로직을 짤 수 있다.

 

 

Vector2 rayOrigin = new Vector2(transform.position.x, transform.position.y); //현재 좌표

// x 축 양의 방향으로 레이 쏘기
RaycastHit2D[] hitsRight = Physics2D.RaycastAll(rayOrigin, Vector2.right, rayX, LayerMask.GetMask("Monster"));

        foreach (var hit in hits)
        {
            // 현재 충돌한 게임오브젝트와 충돌한 게임오브젝트가 같지 않고, 충돌한 객체가 Monster 컴포넌트를 가지고 있을 경우 실행된다. 
             if (hit.collider.gameObject != gameObject && hit.collider.TryGetComponent(out Monster monsterComponent))
             {
                 // 몬스터 비활성화.
                 monsterComponent.gameObject.SetActive(false);
                 GameManager.Instance.scoreManager.AddScore(monsterComponent.score);
             }
           
        }

 

 

이러면 내가정한 x축(코드상에서 rayX) 만큼 ray를 right방향으로 쏴서 LayerMask.GetMask()를 통해 Monster객체들을 SetActive(False) 하는 동작을 수행할 수 있다.

 

if문 내의 TryGetComponent 는 TryParse와 비슷한 느낌으로 true false를 반환하는 bool값인데,

TryGetComponent(out T component) 이며 특정 타입의 컴포넌트를 찾는데 사용되며 컴포넌트를 찾았을 경우 true 아니면 false를 반환한다.