본문 바로가기
유니티 공부/Unity

Unity - Raycast, 좌표계, LayerMask, Tag

by 코딩하는 돼징 2023. 2. 19.
반응형

광선을 쏴서 충돌 되는 물체가 있는지 없는지를 검사


Raycast와 관련있는 함수들

1. Draw ray

public static void DrawRay(Vector3 start, Vector3 dir, Color color = Color.white, float duration = 0.0f, bool depthTest = true);

파라미터

start : ray 시작 지점

dir : ray 방향

color : ray 색깔

duration : ray 길이

반환

Draws a line from start to start _ dir in world coordinates

ex)
Debug.DrawRay(transform.position, Vector3.forward, Color.red);

ex)
Debug(transform.position + Vector3.up, Vector3.forward*10, Color.red);

2. Physsics.Raycast

public static bool Raycast (Vector3 origin, Vector3 direction, float maxDistance= Mathf.Infinity, int layerMask= DefaultRaycastLayers, QueryTriggerInteraction queryTriggerInteraction= QueryTriggerInteraction.UseGlobal);

파라미터

origin : ray 위치

direction : ray 방향

maxDistance : ray 최대 길이

int lyaerMask : 레이어 번호

반환

bool True if the ray intersects with a Collider, otherwise false.

ex)

Raycasthit hit; // 레이캐스트에 닿았을때 hit에 저장

Physics.Raycast( gameObject.transform.position, gameObject.transform.forward, out hit, 10);

if(hit.collider.name == "Cube")

3. RaycastHit[] hits;

위 처럼 Raycasthit hit 에는 하나만 충돌되기 때문에 충돌되는 모든 오브젝트를 입력시키고 하면 RaycastAll 함수를 써야한다.

void Update()
{
    Vector3 look = transform.TransformDirection(Vector3.forward); // local에서 world로 변환
    Debug.DrawRay(transform.position + Vector3.up, look * 10, Color.red);
    RaycastHit[] hits;
    hits = Physics.RaycastAll(transform.position, look , 10);
    foreach(RaycastHit hit in hits)
    {
        Debug.Log($"Raycast !{hit.collider.gameObject.name}");
    }
}

2. 좌표계 

Local <-> World <-> [ViewPort <-> Screen(화면)]

Local : gameObject의 자체 좌표 공간World : 게임 세계 전체의 좌표 공간이다. 게임 오브젝트의 world position은 게임 세계의 원점에 해당 오브젝트까지의 거리이다.Viewport Space : 카메라 시점에서 볼 수 있는 화면의 상대적인 좌표 공간이다.Screen : 실제 화면의 필셀 좌표이다.

01 Screen 좌표 = 현재 마우스 좌표를 픽셀 좌표

Debug.Log(Input.mousePosition);

2D 좌표이므로 Z는 항상 0이 나온다.

게임 화면의 해상도가 100 x 100 이면 오른쪽 끝 상단이 (100,100,0) 으로 나온다.


02 ViewPort

Debug.Log(Camera.main.ScreenToViewportPoint(Input.mousePosition));

화면 비율 0~1 사이로 표시 (0,0,0) ~ (1,1,0)


3. 게임 화면에 마우스를 클릭하면 그 위치를 월드 좌표계로 변환하기

01 마우스 커서의 Screen 좌표를 구하고 World 좌표로 바꾸기

public Vector3 ScreenToWorldPoint(Vector3 position);

파라미터

position : A screen space position (often mouse x, y), plus a z position for depth (for example, a camera clipping plane).

Vector3 mousePos = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y,Camera.main.nearClipPlane));

Z축에서는 world좌표로 향하는 방향을 구해서 그 방향으로 Raycast를 쏘는 것이므로 값이 중요하지 않다.


02 카메라의 현재 위치로부터 01에서 구한 마우스 위치와 World 좌표로 향하는 방향을 구하기

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;

dir는 마우스 위치에서 카메라의 위치를 빼므로 near에 해당하는 방향벡터이다.


03 dir 방향으로 Raycast 를 쏘면 마우스가 클릭했던 그 오브젝트와 충돌

Debug.DrawRay(Camera.main.transform.position, dir * 100.0F, Color.red, 1.0f);
RaycastHit hit;
if (Physics.Raycast(Camera.main.transform.position, dir, out hit, 100.0F))
{
 Debug.Log($"Raycast Camera @ {hit.collider.gameObject.name}");
}

Physics.Raycast

메인 카메라의 현재 위치로부터 / dir 방향으로 메인 카메라의 현재 위치로부터 마우스 클릭한 화면상의 좌표를 월드 좌표로 변환한 곳을 향하는 방향 / 100.0f 길이의 광선을 쏘고 / 충돌한 오브젝트가 있다면 그 정보를 hit에 담은 후 true를 리턴한다.


4. 마우스 버튼 입력 처리

01 마우스 왼쪽 버튼을 눌렀을 때의 처리

if(Input.GetMouseButtonDown(0))

02 마우스 왼쪽 버튼을 누르고 있는 도중의 처리

if(Input.GetMouseButton(0))

03 마우스 왼쪽 버튼을 뗄 때의 처리

if(Input.GetMouseButtonUp(0))

0 : 마우스 왼쪽 버튼

1 : 마우스 오른쪽 버튼

2 : 마우스 휠 버튼


4. ScreenPointToRay

Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

호출한 카메라 위치로부터 픽셀 단위의 화면상 좌표의 실제 월드 좌표로 향하는 방향의 Ray(광선)을 리턴한다.


위와 같은 과정이다.

Vector3 mousePos = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, Camera.main.nearClipPlane));
Vector3 dir = mousePos - Camera.main.transform.position; // 마우스 위치에서 카메라 포지션을 뺀거니까 카메라위치에서 near향하는 방향벡터 
dir = dir.normalized;

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

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

Raycast에 시작 위치와 방향을 넘기는 대신 광선 자체의 ray를 넘겨준다.


5. LayerMask

오브젝트에게 해당 Layer를 붙이면 그 Layer에 해당하는 오브젝트들을 대상으로만 Raycastring 할 수 있다.

LayerMask mask = LayerMask.GetMask("Monster")| LayerMask.GetMask("Wall");

6. Tag

옷에 태그를 붙이는 것 처럼 추가적인 정보를 남기는 것

GameObject.FindGameObjectsWithTag("Monster");
Debug.Log($"Raycast Camera @ {hit.collider.gameObject.tag}");

 

 

 

 

 

 

 

 

 

참고 :  본 내용은 MMORPG  PART3 강의를 수강하여 작성하였습니다.

https://www.inflearn.com/course/mmorpg-%EC%9C%A0%EB%8B%88%ED%8B%B0/dashboard

 

 

 

 

 

 

 

 

 

반응형

댓글