unity/유니티 초보

Unity: raycasting - Object확인 방법

rimugiri 2023. 1. 5. 16:40
728x90

raycasting을 이용하여 게임상 화면에 클릭한 공간에 물체가 있는지 여부를 확인해보자

Local , World, Viewport, Screen 좌표

 

local : object 자신의 좌표

World : global 좌표

Sreen : 게임화면상 좌표

Viewport : Screen 좌표를 비율로 표시한 좌표 (0~1, 0~1, 0)으로 나타난다

 

1. 우선 스크린의 마우스 좌표를 워드좌표로 변경한다 

//Screen좌표 즉 2D상의 좌표를 world좌표로 3D좌표로 바꿔준다
//Camera.main.nearClipPlane는 카메라의 Near을 나타낸다 
Vector3 mousePos = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, Camera.main.nearClipPlane));

 

2. z축의 방향벡터를 알아낸다

//방향벡터
Vector3 dir = mousePos - Camera.main.transform.position;
//정규화
dir = dir.normalized;

3. 워드좌표와 방향벡터를 이용하여 클릭한 공간에 물체가 있는지 확인한다

// 마우스가 클릭되었을때
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;

    RaycastHit hit;
    
    // 매개변수는 순서대로 카메라 위치, 거리, 색, 지속시간을 나타낸다 -> 이 외에 다양한 오버로드가 존재한다
    Debug.DrawRay(Camera.main.transform.position, dir * 10.0f, Color.red, 1.0f);
    
    // 클릭한 위치에 물체가 존재하면 hit에 정보가 담기고 true가 반환된다
    // 매개변수는 순서대로 카메라 위치, 방향벡터, 정보담는 변수, 거리(기본값은 무한이다)
    if (Physics.Raycast(Camera.main.transform.position, dir, out hit, 10.0f))
    {
    	// 물체의 이름을 띄어준다
        Debug.Log($"Raycast Camera {hit.collider.gameObject.name}!");
    }
}

 

좀 더 코드를 간결하게 하면

 

 

 

if (Input.GetMouseButtonDown(0))
{
	// 이를 이용하여 3개의 코드를 줄일 수 있다
    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

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

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

 

위 코드에서는 특정거리에 존재하는 물체중 가장가까운 물체만 확인이되는데 여러 물체를 확인하기 위한 코드

RaycastHit[] hits;
hits = Physics.RaycastAll(transform.position, dir, 10);

foreach (RaycastHit hit in hits)
{
    Debug.Log($"Raycast {hit.collider.gameObject.name}");
}

 

마지막으로 layer설정으로 원하는 계층의 물체만 뽑아내는 코드

if (Input.GetMouseButtonDown(0))
{
    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

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

    LayerMask mask = LayerMask.GetMask("Monster") | LayerMask.GetMask("Wall");
    //int mask = (1 << 8) | (1 << 9);

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

나는 layer 8번엔 Monster을 9번에는 Wall을 설정하여 위코드로 Monster와 Wall물체만 확인되게 설정하였다

728x90