Ray에 대해 알아보기 전에 유니티의 Screen에서 마우스가 어떻게 좌표로 표시되는지 알아보기
Screen에서 표시되는 마우스 좌표
간단하게 디버깅으로 현재 마우스 위치를 출력하게 하는 것으로 어떤 좌표를 사용하는 것인지 알 수 있다.
마우스의 좌표는 screen 좌표와 viewPort 좌표로 구분되는데
screen 좌표는 화면의 픽셀당 좌표를 나타내고, viewPort 좌표는 스크린 좌표랑 비슷하지만 그 정도를 비율로 나타낸다.
Debug.Log(Input.mousePosition);//Screen
Debug.Log(Camera.main.ScreenToViewportPoint(Input.mousePosition)); // viewport

지금까지는 Game 화면만 놓고 마우스의 좌표를 생각했다.
3D상의 세상을 2D로 변환하여 마우스의 좌표를 계산하는 것은
main camera를 보면 카메라의 앞쪽 사다리꼴의 작은 사각형 화면에서 카메라의 로컬 좌표를 통해 이루어진다.
글로벌 좌표를 카메라의 로컬로 변환하는 것은 다른 문제지만
아무튼 camera의 로컬 좌표를 토대로 마우스의 좌표를 계산하는 것이었다.
Raycasting
Ray는 특정 방향으로의 선을 의미하며, 이 선을 사용하여 충돌 감지, 시선 추적, 레이저 효과 등을 구현할 수 있다.
유니티에서 Ray를 사용하려면 Physics.Raycast 메서드를 사용한다.
이 메서드는 특정 방향으로 광선을 쏘아 해당 광선이 충돌하는 객체를 감지한다. 이를 통해 다양한 물리적 상호작용을 처리할 수 있다.

나는 Ray를 이용해서 마우스 위치로 오브젝트를 끌고 오게 해봤다.
오브젝트에 콜라이더를 붙이고 (자꾸 깜빡한다) 마우스 위치를 오브젝트 위치에 대입하는 방식으로 드래그를 구현했다.
이런 방식으로 Ray를 응용할 수 있겠다.
아래는 Raycast의 기본적인 템플릿이다.
- origin: Vector3 - Ray가 시작되는 위치.
- direction: Vector3 - Ray가 향하는 방향.
- out hitInfo: RaycastHit - 충돌한 물체의 정보를 저장하는 변수.
- maxDistance: float - Ray가 투사될 최대 거리 (100.0f는 100 유니티 단위를 의미).
- layerMask: int - Ray가 감지할 레이어를 지정.
void Update()
{
Ray ray = new Ray(Camera.main.transform.position, Camera.main.transform.forward);
RaycastHit hitInfo;
// Ray를 투사하여 최대 100 유니티 단위 거리 내에서 충돌 여부를 검사
if (Physics.Raycast(ray, out hitInfo, 100.0f))
{
Debug.Log("Hit: " + hitInfo.collider.name);
}
}
결과적으로 Physics.Raycast 는 RaycastHit 이라는 배열을 만들고, 존재하는지 유무를 bool 값으로 반환한다.
bool hit = Physics.Raycast(ray, out RaycastHit hitInfo, maxDistance);
정리해보면
Ray 메서드 중, Raycast 는 Ray가 어떤 물체와 충돌했는지 검사하는 기능을 제공하고
RaycastHit 클래스는 Ray가 충돌한 객체에 대한 다양한 정보들을 제공한다.
void Update() { // 카메라의 정면 방향으로 Ray 생성
Ray ray = new Ray(Camera.main.transform.position, Camera.main.transform.forward);
RaycastHit hitInfo;
// Ray가 충돌했는지 검사
if (Physics.Raycast(ray, out hitInfo, 100.0f))
{
// 충돌한 객체의 이름을 출력
Debug.Log("Hit: " + hitInfo.collider.name);
// 충돌 지점 출력
Debug.Log("Hit Point: " + hitInfo.point);
// 충돌한 표면의 법선 벡터 출력
Debug.Log("Hit Normal: " + hitInfo.normal);
// Ray의 시작점에서 충돌 지점까지의 거리 출력
Debug.Log("Hit Distance: " + hitInfo.distance);
}
}
만약 마우스로 누른 오브젝트의 이름을 출력하고 싶다면 RaycastHit 을 사용하자
void Update() {
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitInfo;
if (Physics.Raycast(ray, out hitInfo))
{
Debug.Log("Hit: " + hitInfo.collider.name);
}
}
}
간단하게 이미 정의되어 있는 Ray를 사용하면 편하지만
직접 Vector3를 이용해서 구현해볼 수도 있다
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
지금까지 사용했던 위와 같은 코드는
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;
이렇게 Vector3로도 구현 가능하다.
위에서 설명했던 screen상 mouse 좌표의 계산을 보면 Ray의 이해에 조금 더 도움이 되는 것 같다.