주녘공부일지

[Unity3D] Physics.Raycast (+LayerMask) 본문

GameDevelopment/[Unity] Class

[Unity3D] Physics.Raycast (+LayerMask)

주녘 2022. 2. 24. 21:33

Physics.Raycast란?

충돌을 Collider로 감지하는 레이저 광선 ( Ray )

- UnityEngine에 선언되어 있는 구조체 Physics

 

Raycasting은 상당히 무거운 작업(부하를 많이 줌)이므로 최적화를 하는 것이 중요 

- 인스펙터에서 Layer를 추가해 LayerMask를 활용하여 영역을 나누어 연산 최적화 ( 글 하단 4, 5번 )

- 매쉬 콜라이더가 너무 복잡할 경우엔 충돌 연산용 매쉬 콜라이더를 만들어 사용

 


1. 3D 플레이어가 바라보는 방향의 물체 감지 예제

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestRaycast : MonoBehaviour
{
    void Update()
    {
    	Vector3 look = transform.TransformDirection(Vector3.forward); // Local -> World
        Debug.DrawRay(transform.position + Vector3.up, look * 10, Color.red);

        RaycastHit hit;
        if (Physics.Raycast(transform.position + Vector3.up, Vector3.forward, out hit, 10))
        {
        	// Ray에 충돌이 감지되면 충돌된 오브젝트의 이름을 출력
        	Debug.Log($"Raycast : {hit.collider.gameobject.name}");
        }
    }
}

Physics.Raycast() : Ray를 발사, 첫번째 닿는 타겟만 감지

Debug.DrawRay() : 씬에서 Ray의 시각화를 가능하게 해주는 함수 ( 매 프레임 호출 )

RaycastHit : UnityEngine에 선언되어 있는 구조체

 

위의 로직에서 DrawRay()와 Raycast()는 같은 영역

+ Vector3.up을 해준 이유는 3D플레이어의 중앙부분에서 레이저 광선을 쏘기 위함

 

Physics.Raycast(Ray의 시작 좌표, 발사할 방향벡터, 검출할 레이어, Ray 도달 거리) // 오버로딩

1-1) 3D 플레이어가 바라보는 방향의 물체들 감지 예제

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestRaycast : MonoBehaviour
{
    void Update()
    {
    	Vector3 look = transform.TransformDirection(Vector3.forward); // world -> local
        Debug.DrawRay(transform.position + Vector3.up, look * 10, Color.red);

        RaycastHit[] hits; // 배열로 선언
        hits = Physics.RaycastAll(transform.position + Vector3.up, look, 10);

        foreach(RaycastHit hit in hits)
        {
            // Ray에 충돌이 감지되면 충돌된 오브젝트들의 이름을 출력
            Debug.Log($"Raycast {hit.collider.gameObject.name}!");
        }
    }
}

Physics.RaycastAll() : Ray를 발사, Ray에 닿는 모든 타겟을 감지

Debug.DrawRay() : 씬에서 Ray의 시각화를 가능하게 해주는 함수 ( 매 프레임 호출 )

RaycastHit : UnityEngine에 선언되어 있는 구조체

 

위의 로직에서 DrawRay()와 RaycastAll() 은 같은 영역

+ Vector3.up을 해준 이유는 3D플레이어의 중앙부분에서 레이저 광선을 쏘기 위함

 

Physics.Raycast(Ray의 시작 좌표, 발사할 방향벡터, 검출할 레이어, Ray 도달 거리) // 오버로딩

 


2. Unity3D의 Main Camera

유니티의 메인 카메라는 3D 화면을 절두체 모양으로 투영시켜 2D로 스크린에 나타냄

 

 

Near : 메인 카메라 원점과 가장 가까운 절두체 윗면(직사각형)의 거리

Far : 메인 카메라 원점과 가장 먼 절두체 밑면(직사각형)의 거리

 

https://docs.unity3d.com/kr/2018.4/Manual/class-Camera.html

 

카메라 - Unity 매뉴얼

카메라 는 월드를 캡처하여 플레이어에게 보여주는 장치입니다. 카메라를 커스터마이즈 및 조정하여 게임의 프레젠테이션을 독창적으로 만들 수 있습니다. 하나의 씬에 카메라를 원하는 만큼

docs.unity3d.com

 

1) Screen 좌표계 : 화면 좌표계로 화면의 좌측 하단 끝을 원점으로 하는 평면 절대 좌표계

2) Viewport 좌표계 : 화면의 좌측 하단 끝을 원점으로 하는 평면 상대 좌표계 // 우측 하단 끝 좌표 - (1, 1)  

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestCollision : MonoBehaviour
{
    void Update()
    {
        Debug.Log(Input.mousePosition); // 1) Screen

        Debug.Log(Camera.main.ScreenToViewportPoint(Input.mousePosition)); // 2) Viewport
    }
}

2-1) 카메라를 스크린의 클릭한 물체를 감지하는 예제

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestCollision : MonoBehaviour
{
    void Update()
    {
        if (Input.GetMouseButtonDown(0)) // 왼쪽 마우스 클릭
        {
            Vector3 mousePos = Camera.main.ScreenToWorldPoint(new Vector3(
            	Input.mousePosition.x, Input.mousePosition.y, Camera.main.nearClipPlane));
            Vector3 dir = mousePos - Camera.main.transform.position; // 카메라 위치와 절두체의 가장 가까운 포인트
            dir = dir.normalized; // 0~1로 정규화

            Debug.DrawRay(Camera.main.transform.position, dir * 100f, Color.red, 1.0f);

            RaycastHit hit;
            if (Physics.Raycast(Camera.main.transform.position, dir, out hit, 100f))
            {
                Debug.Log($"Raycast Camera @ {hit.collider.gameObject.name}");
            }
        }
    }
}

Physics.Raycast() : Ray를 발사, 첫번째 닿는 타겟만 감지

Debug.DrawRay() : 씬에서 Ray의 시각화를 가능하게 해주는 함수 ( 매 프레임 호출 )

RaycastHit : UnityEngine에 선언되어 있는 구조체로 raycast로부터 정보를 얻기 위해 사용

 

+ 위의 로직에서 DrawRay()와 Raycast()는 같은 영역

+ Physics.Raycast(Ray의 시작 좌표, 발사할 방향벡터, 검출할 레이어, Ray 도달 거리) // 오버로딩

2-2) 위와 같은 예제

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestCollision : MonoBehaviour
{
    void Update()
    {
        if(Input.GetMouseButtonDown(0)) // 왼쪽 마우스
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

            Debug.DrawRay(Camera.main.transform.position, ray.direction * 100f, Color.red, 1.0f);
            // ray.direction : 정규화 된 정보

            RaycastHit hit;
            if (Physics.Raycast(ray, out hit, 100f, 0))
            {
                Debug.Log($"Raycast Camera @ {hit.collider.gameObject.name}");
            }
        }
    }
}

- 위 두 예제는 같은 기능을 하는 로직으로, 게임상에서 마우스가 클릭되면 클릭한 좌표로 Ray가 발사되며 (DrawRay로 씬에 표시됨) Ray에 콜라이더를 가진 물체가 닿을 시에 콘솔에 닿은 콜라이더를 가진 오브젝트의 이름을 찍는 예제

 

Camera.main.ScreenPointToRay() : 카메라로 부터의 스크린의 점을 통해 레이를 반환

 


3. Tags & Layers 세팅 (예제)

User Layer는 0 ~ 31번까지 존재 ( int형 : 32bit )

 

- 비활성화되어 있는 Builtin Layer는 Unity가 이미 점유하고 있는 상태

3-1) LayerMark를 활용한 예제 ( 2-2 확장 )

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestCollision : MonoBehaviour
{
    void Update()
    {
        if(Input.GetMouseButtonDown(0)) // 왼쪽 마우스
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

            Debug.DrawRay(Camera.main.transform.position, ray.direction * 100f, Color.red, 1.0f);

            LayerMask mask = LayerMask.GetMask("Monster") | LayerMask.GetMask("Wall");
            // int mask = (1 << 6) | (1 << 7);// int형으로 32비트인 Layer를 제어 (위와 같은 로직)
            
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit, 100f, mask))
            {
                Debug.Log($"Raycast Camera @ {hit.collider.gameObject.name}");
            }
        }
    }
}

- LayerMark를 활용하여 특정 아이들만 레이캐스팅하는 것으로 최적화

'GameDevelopment > [Unity] Class' 카테고리의 다른 글

[Unity] StateMachineBehaviour  (0) 2022.03.23
[Unity3D] Camera  (0) 2022.03.01
[Unity3D] Collision (충돌)  (0) 2022.02.23
[Unity3D] Rotation (회전)  (0) 2022.02.21
[Unity3D] Vector3  (0) 2022.02.21