호빵의 IT 개발소

[MMO RPG] Raycasting 본문

C#, 유니티/MMO RPG 만들기 기초(클라이언트)

[MMO RPG] Raycasting

호빵Stack 2022. 1. 23. 01:18

Raycasting이란 레이저를 쏘는 것이라고 생각하시면 됩니다. 이 레이저와 충돌하는 collider에 대한 정보를 얻을 수 있습니다.

 

일단 기본적으로 모델에 배꼽부분에 Raycasting을 해보겠습니다.

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

public class RaycastingTest : MonoBehaviour
{
    void Update()
    {
        Vector3 look = transform.TransformDirection(Vector3.forward);
        Debug.DrawRay(transform.position + Vector3.up, look * 10, Color.red);

        RaycastHit hit;
        if (Physics.Raycast(transform.position + Vector3.up, look, out hit, 10))
        {
            Debug.Log($"Raycast {hit.collider.gameObject.name}!");
        }

    }
}

해석


Vector3 look = transform.TransformDirection(Vector3.forward); //모델이 바라보는 방향으로 레이저가 나오도록 설정
Debug.DrawRay(transform.position + Vector3.up, look * 10, Color.red); //레이저 위치는 모델 위치에서 위로 1.0f 올라간 뒤 바라보는 방향으로 * 10에 길이 만큼 출려된다. 레이저 색깔은 빨간색이다.

RaycastHit hit;  //RaycastHit을 선언하여 충돌 정보를 반환한다.
if (Physics.Raycast(transform.position + Vector3.up, look, out hit, 10)) //레이저에 충돌하면
{
Debug.Log($"Raycast {hit.collider.gameObject.name}!"); //충돌한 물체에 이름을 log로 출력한다.

}


만약 Raycast 선이 안보일 경우 상단에 Gizmos라는 부분을 클릭하면  Raycast선이 보이게 됩니다.

 

지금 사진을 보면 log출력에서 앞에 있는 Cube One 만 충돌되고 뒤에 있는 Cube Two까지는 충돌 정보가 넘어오지 않고 있습니다. 관통해서 충돌 정보를 가져오는 코드를 작성해 보겠습니다.

여기서 변경된 부분은 여러개의 정보를 받기 위해 RaycastHit은 배열로 변경되고 RaycastAll을 사용합니다. 마지막으로 raycast되는 부분을 foreach문을 사용하여 하나씩 계속 순회하도록 조건문을 작성하였습니다.

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

public class RaycastingTest : MonoBehaviour
{
    void Update()
    {
        Vector3 look = transform.TransformDirection(Vector3.forward);
        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)
        {
            Debug.Log($"Raycast {hit.collider.gameObject.name}!");
        }

    }
}

 


Local 좌표 <-> World 좌표 <-> viewport <-> Screen(화면)

 

main카메라에서 마우스 클릭으로 Raycasting

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

public class RaycastingTest : MonoBehaviour
{
    void Update()
    {
        if (Input.GetMouseButton(0)) //마우스 좌클릭을 했을 때
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); //메인 카메라에 화면을 통해 마우스를 사용하여 ray 출력

            Debug.DrawRay(Camera.main.transform.position, ray.direction * 100.0f, Color.red, 1.0f); //메인 카메라 위치 기준, 길이 : ray에 기본값 * 100, 색깔 : 빨강, 레이저 포인트 1초 유지)

            RaycastHit hit;
            if (Physics.Raycast(ray, out hit, 100.0f)) //길이 100 레이저가 어떤 물체와 충돌을  했다면
            {
                Debug.Log($"Raycast Camera @ {hit.collider.gameObject.name}"); //충돌 물체의 이름을 log에 출력
            }
        }
    }
}


원하는 Layer만 Raycasting 하기

-raycasting이 정말 무거운 작업이고 신중하게 써야하는 작업입니다. 만약 큐브라는 물체가 수천개가 되게 되면 raycasting을 할때마다 큰 부하를 받게 됩니다. 그래서 필요한 오브젝트만 raycasting을 하기 위해 Layer를 사용하게 됩니다.

 

1. 우선 Layer를 만들어 봅시다. 큐브를 클릭한 뒤 우측 상단에 Layer를 클릭하게 되면 아래 Add Layer를 클릭해줍니다.

2. Layer 빈곳에 Monster, Wall이라는 Layer를 생성해 줍니다.

 

3. 물체에 Layer를 적용시켜 줍니다. Plane에는 Layer Wall를 적용시키고 나머지 Cube는 Layer Monster로 적용합니다. 

4. 코드 작성

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

public class RaycastingTest : MonoBehaviour
{
    void Update()
    {
        if (Input.GetMouseButton(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

            Debug.DrawRay(Camera.main.transform.position, ray.direction * 100.0f, Color.red, 1.0f);
			
            LayerMask mask = LayerMask.GetMask("Monster") | LayerMask.GetMask("Wall"); //Monster, Wall를 불러옴
            
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit, 100.0f, mask)) //mask를 추가하여 Monster와 Wall Layer만 Raycast 적용
            {
                Debug.Log($"Raycast Camera @ {hit.collider.gameObject.name}");
            }
        }
    }
}

 

 

 

---------------------------------------------------------------------------------------------------------------------------

참고 : [인프런] Rookiss님의 [C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part3: 유니티  엔진

Comments