본문 바로가기

UNITY

UNITY_20231020[Ray in UNITY3D]

또 슈팅 게임 얘기로 시작한다.

 

슈팅 게임을 하다 보면, 게임 내에서 총알이 발사되는 방식을 2가지로 구분할 수 있다.

하나는 직접 투사체 오브젝트를 날려서 이것과의 충돌 이벤트를 일으키는 PROJECTILE 방식.

다른 하나는 발사 지점으로부터 일정한 길이의 레이저(쉽게 표현했다)를 생성해 이 레이저가 특정 오브젝트와 충돌을 일으키게 하는 HITSCAN방식.

두 방법 모두 현재 슈팅게임에 활발히 적용되고 있는 방식이고, 각각의 쓰임새가 있다.

이 중 HITSCAN방식에 사용되는 RAY기능에 대해 알아본다.


RAY, 광선, 즉 빛이다. 발사와 동시에 충돌반응을 일으킬 수 있다는 말이다.

유니티에서 RAY변수는 Ray 클래스에 의해 생성되고, 기본적으로 원점origin과 방향direction요소를 포함하고 있으며, 대체로 Physics클래스의 Raycast메서드와 함께 사용된다.

위의 내용만 알고 있으면 얼추 Ray를 사용할 기본은 갖췄다.

아래는 유니티 공간에서 Ray를 쏴, 특정 오브젝트를 맞추고, 그 오브젝트의 이름을 출력하는 코드다.

private void ShootRay()
{
	Ray ray;
	
	ray.origin = transform.position;
	ray.direction = transform.forward;
	
	RaycastHit hit;
	
	if (Physics.Raycast(ray.origin, ray.direction, out hit))
	{
		Debug.Log(hit.collider.gameOjbect.name);
	}
}

Ray를 발사하는 Raycast메서드에는 다양한 오버라이드가 있다.

Physics.Raycast(Vector3 origin, Vector3 direction, out RaycastHit hitInfo)

Physics.Raycast(Vector3 origin, Vector3 direction, out RaycastHit hitInfo, float maxDistance)

Physics.Raycast(Vector3 origin, Vector3 direction, out RaycastHit hitInfo, float maxDistance, int layerMask)

Physics.Raycast(Ray ray, out RaycastHit hitInfo, float maxDistance)

우선 기본적으로 발사 원점, 방향, 충돌 지점의 정보가 필요하다.(원점&방향이 없는 오버라이드는 Ray변수에 미리 그 정보가 들어가 있는 경우다.)

어디로부터, 어느 방향으로, 무엇과, 얼마나 멀리, 경로 상의 충돌체 중 무엇을 받아올 것인가를 정할 수 있다.

 

RaycastHit 클래스의 변수가 필수적인데, 이 RaycastHit클래스가 있음으로써 충돌 시의 정보를 받아올 수 있다.

RaycastHit 클래스는 아래와 같은 정보를 갖고 있다. 아래 표가 다는 아니다. 내가 이해한 것만 일단 작성한다.

collider Ray와 충돌한 오브젝트의 collider 정보
distance Ray와 충돌한 오브젝트와 Ray원점 간의 거리 정보
rigidbody Ray와 충돌한 오브젝트의 rigidbody 정보
normal Ray가 충돌한 면의 수직 방향 정보
point Ray가 충돌한 딱 그 지점의 위치 정보
transform Ray와 충돌한 오브젝트의 위치 정보

아래는 참고한 UnityDocs다.

https://docs.unity3d.com/kr/530/ScriptReference/RaycastHit.html

 

UnityEngine.RaycastHit - Unity 스크립팅 API

Structure used to get information back from a raycast.

docs.unity3d.com

 

+ Ray 변수에 값을 할당하는 방법에는 여러가지가 있는데, 그 중 가장 대표적인 경우를 작성한다.

 

#1) Camera.main.ScreenPointToRay(Input.MousePosition);

  • 화면에 비치는 곳에서 마우스가 가리키는 지점에 Ray를 만든다.
  • 어떤 경우에 쓸까? 바로 떠오르는 경우는 쿼터뷰 3D게임이나 탑다운뷰 게임에서 마우스 클릭한 지점으로 플레이어 오브젝트를 이동시킬 때 쓰면 되겠다. 롤, 스타크래프트, 체스 등이 해당되겠다.
private RaycastHit hit;

void Update()
{
    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
	// MainCamera가 보는 화면 내에서 마우스 위치를 지속적으로 할당한다.
    
    if(Input.GetMouseButtonDown(0)) // 마우스 L클릭 시
    {
        if (Physics.Raycast(ray, out hit, Mathf.Infinity)) // 마우스가 가리키는 방향으로 Ray를 쏘고
            Debug.Log(hit.distance); // 충돌한 지점과 발사 원점 간의 거리를 출력한다.
    }
}

 

 

#2) Camera.main.ScreenPointToRay(new Vector3(Screen.width / 2, Screen.height / 2));

  •  화면 정중앙에 Ray를 생성한다.
  • 카메라가 마우스 위치 변화량에 따라 회전값이 달라지는 기능이 구현돼 있다면, 화면 중앙에 오는 물체와 상호작용한다던가, 화면 중앙으로 물리적 이벤트를 일으킬 수 있을 것이다.
  • 어떤 경우에 쓸까? 당연히 FPS/TPS 슈팅 장르에 필수적이다.