게임을 하다보면 마우스로 물체를 선택해서 상호작용하는 것을 많이 볼 수 있다.
많은 게임들이 그러한 기능을 구현해놓았으며 또 많은 프로그램들이 이를 사용하는 것을 알 수 있다. 대표적으로 디아블로에서 마우스로 아이템에 마우스로 가져다대면 해당 아이템의 정보를 띄우는 것을 볼 수 있다. 프로그램들은 시작될 때, 컴퓨터의 마우스 위치에 대한 정보를 갖고 있지 않다. 그래서 사용자가 마우스를 사용할려면 마우스위치에 대한 정보를 프로그램에게 넘겨주면서 이를 프로그램 상에서 나타내주어야 한다.
2D 게임 상에서는 화면처럼 2차원이기에 마우스의 좌표를 바로 넘겨서 사용할 수 있을 것이다. 하지만 3차원에서는 3개의 좌표로 마우스의 위치를 나타내야 하는데 이를 정확하게 위치를 나타내기란 매우 어렵다. 그래서 많이 쓰는 방법은 카메라 위치에서 마우스 위치로 향하는 벡터를 가진 선을 만들고 이 선에 부딪혔을 때, 해당 물체에 대한 정보를 반환하게 하는 것으로 구현한다.
이를 위해 Raycast라는 것을 사용하며 벡터방향으로 선을 만들어 선과 부딪히는 물체에 대한 정보를 반환한다.


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PickingExample : MonoBehaviour
{
[SerializeField]
private GameObject[] objs = null;
private Camera mainCam = null;
private void Awake() {
mainCam = Camera.main;
}
private void Update()
{
ResetColor();
GameObject go = ModernPickingProcess();
if (go != null) SetColorAtGo(go);
//PickingProcess();
}
private GameObject PickingProcess() {
Vector3 mousePos = Input.mousePosition;
mousePos.z = mainCam.nearClipPlane;
Vector3 toWorld = mainCam.ScreenToWorldPoint(mousePos);
Vector3 dir = (toWorld - mainCam.transform.position);
RaycastHit hit;
if (Physics.Raycast(mainCam.transform.position, dir, out hit)) {
return hit.transform.gameObject;
}
Debug.DrawRay(mainCam.transform.position,dir,Color.red);
return null;
}
벡터를 사용하여 Ray와 부딪힌 물체에 대한 GameObject 정보를 반환한다.
이때, 벡터에 대한 정보를 만들기 위해 화면 상의 마우스의 위치와 게임 속 카메라의 위치를 받아서 이를 사용해 벡터에 대한 정보를 만들어 낸다. 그리고 반환 정보는 hit에 저장된다.
private GameObject ModernPickingProcess() {
Ray ray = mainCam.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit)) {
return hit.transform.gameObject;
}
return null;
}
Ray를 바로 생성하여 벡터 계산에 대한 구현없이 Raycast를 사용할 수 있다.
또한, 위 코드와 다른 점은 Raycast의 오버로딩이다. Raycast 메소드에 들어가는 파라메터 위에서는 시작점의 위치와 해당 방향으로 되어있지만 여기서는 ray객체에 대한 정보를 바로 넣어 준다.
private void ResetColor()
{
foreach (GameObject go in objs)
{
MeshRenderer mr = go.GetComponent<MeshRenderer>();
mr.material.SetColor("_Color", Color.white);
}
}
private void SetColorAtGo(GameObject _go)
{
MeshRenderer mr = _go.GetComponent<MeshRenderer>();
mr.material.SetColor("_Color", Color.red);
}
}
위에서는 Raycast 메소드에서 단순히 부딛힌 물체의 정보를 바로 반환하게 했지만 설정 상으로 물체에 대한 정보를 차단할 수 있고 이를 LayerMask를 통해 사용이 가능하다.
physics.Raycast(ray,out rayhit, -LayerMask-)
Raycast는 15가지 정도의 오버로드가 가능하며 차후 기회가 될 때, 확인해보는것이 괜찮을 듯 하다.