본문 바로가기

Unity3D/C#

유니티 클릭한 오브젝트 찾기 (Camera.ScreenPointToRay, Physics.Raycast)

반응형

Raycast Click

전략 게임에서 유닛을 고르거나 방치형 게임에서 상자를 눌러 여는 것처럼, 화면을 클릭했을 때 그 아래에 있는 3D 오브젝트를 알아내야 하는 경우가 많습니다. 마우스 위치는 화면의 픽셀 좌표이고 오브젝트는 월드 공간에 있기 때문에 두 좌표를 이어 줄 방법이 필요합니다. Unity에서는 Camera.ScreenPointToRay로 화면 위치에서 카메라가 보는 방향으로 나가는 광선(Ray)을 만들고, Physics.Raycast로 그 광선이 처음 부딪힌 콜라이더를 얻을 수 있습니다. 이번 예시에서는 마우스 왼쪽 버튼을 누른 순간 광선을 쏘아 맞은 오브젝트의 이름을 콘솔에 출력하고, 표시용 오브젝트를 맞은 지점으로 옮겨 보겠습니다.

C# (UNITY 3D)

Check_Click 흐름. 왼쪽 버튼을 누른 프레임에 ScreenPointToRay로 Ray를 만들고 Physics.Raycast로 가장 가까운 Collider를 찾아 이름을 출력하고 marker를 옮기는 순서의 설명 도식입니다. 실제 Unity 화면이 아닙니다.

왼쪽 버튼을 누르면 맞은 콜라이더의 이름을 콘솔에 출력하고, marker를 맞은 지점으로 옮기는 예제입니다.

마우스 입력은 기존 Input Manager의 Input.GetMouseButtonDown과 Input.mousePosition을 사용합니다. Input, Camera, Physics 모두 UnityEngine에 있어 using은 하나입니다.

빈 GameObject에 ClickRaycast.cs를 붙이고, Camera Main에 카메라를, Marker에 표시용 구를 할당합니다. 카메라를 비워 두면 MainCamera 태그가 붙은 카메라(Camera.main)를 찾습니다. 클릭할 오브젝트에는 Collider가 있어야 합니다. 표시용 구의 콜라이더는 지워 두는 편이 좋습니다. 남겨 두면 다음 클릭 때 구가 먼저 맞을 수 있습니다.

using UnityEngine;

//CodeFinder 코드파인더
//From https://codefinder.janndk.com/
public class ClickRaycast : MonoBehaviour
{
    public Camera camera_main;
    public Transform marker;
    public float distance_max = 100f;

    void Start()
    {
        if (camera_main == null)
            camera_main = Camera.main;
    }

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
            Check_Click();
    }

    void Check_Click()
    {
        if (camera_main == null)
            return;

        // 화면의 마우스 위치에서 카메라가 보는 방향으로 광선을 만듭니다.
        Ray ray = camera_main.ScreenPointToRay(Input.mousePosition);
        if (Physics.Raycast(ray, out RaycastHit hit, distance_max))
        {
            Debug.Log("클릭한 오브젝트: " + hit.collider.name);
            if (marker != null)
                marker.position = hit.point;
        }
    }
}

변수(variable)

camera_main(Camera) : 광선을 만들 카메라입니다.

marker(Transform) : 맞은 지점으로 옮길 표시용 오브젝트입니다.

distance_max(float) : 광선이 닿는 최대 거리입니다.

함수(function)

Start : 카메라가 비어 있으면 Camera.main을 넣습니다.

Update : 왼쪽 버튼을 누른 프레임에만 Check_Click을 부릅니다.

Check_Click : 광선을 쏘아 맞은 콜라이더의 이름을 출력하고 marker를 hit.point로 옮깁니다.

주의

Physics.Raycast는 3D 물리의 Collider만 찾습니다. 2D 콜라이더(Collider2D)나 UI 요소는 이 코드로 잡히지 않습니다. 또 Player Settings의 Active Input Handling이 새 Input System만 쓰도록 되어 있으면 Input 클래스를 쓸 수 없으니, 이 예제는 Input Manager를 쓰는 프로젝트를 기준으로 합니다. 이 코드는 Unity 6000.6.3f1에서 컴파일 오류가 없는 것까지 확인했습니다.

참고: Camera.ScreenPointToRay · Physics.Raycast · RaycastHit · Input.GetMouseButtonDown · Camera.main

반응형

Google Play 및 Google Play 로고는 Google LLC의 상표입니다.