전체 코드

1. 화면 좌표계 (Screen, Viewport)

✔️ 화면 좌표계

화면 좌표계는 게임 화면에서 실제로 보이는 좌표 시스템을 의미한다. 이 좌표는 2D로 표현되고, 게임 화면에서 마우스나 객체가 위치한 좌표를 나타낼 때 사용된다. 주로 픽셀 단위로 좌표를 다룬다.

  • Screen 좌표: 화면의 크기(해상도)에 따라 좌표가 다름. 예를 들어, 해상도가 1280x900이라면, (0, 0)은 화면의 왼쪽 하단이고, (1280, 900)은 화면의 오른쪽 상단이 된다.
  • Viewport 좌표: 화면의 크기나 해상도와 관계없이, 0~1 사이의 비율로 좌표를 나타낸다. (0, 0)은 화면의 왼쪽 하단, (1, 1)은 화면의 오른쪽 상단을 나타낸다.

예시 코드: 마우스 위치를 Screen 좌표와 Viewport 좌표로 출력하기

void Update()
{
    // 마우스 위치 출력 (Screen 좌표)
    Debug.Log(Input.mousePosition);  

    // 마우스 위치를 Screen 좌표에서 Viewport 좌표로 변환 후 출력
    Debug.Log(Camera.main.ScreenToViewportPoint(Input.mousePosition));  
}
  • Input.mousePosition: 현재 마우스 위치를 (0, 0) ~ (Screen.width, Screen.height) 범위의 픽셀 좌표로 나타낸다.
  • Camera.main.ScreenToViewportPoint: Screen 좌표계로 나타낸 마우스 위치를 (0, 0) ~ (1, 1) 범위의 비율 좌표로 변환해준다.

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

게임 화면에서 특정 오브젝트를 마우스로 클릭하면 그 위치를 월드 좌표계로 변환해야 한다. 이를 통해 클릭한 지점에서 오브젝트나 캐릭터가 반응할 수 있게 된다. 이 과정을 단계별로 살펴보자.

1️⃣ 마우스를 클릭한 곳의 화면상의 좌표를 월드 좌표로 변환

마우스 커서의 위치는 화면 좌표계(Screen)로 주어지는데, 이를 월드 좌표계(World)로 변환하는 과정이 필요하다.

Vector3 mousePos = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, Camera.main.nearClipPlane));
  • ScreenToWorldPoint: 화면 좌표계에서 월드 좌표계로 변환하는 함수이다. 여기서 중요한 점은 화면 좌표는 Z 값이 없기 때문에 카메라와의 거리를 고려한 Z 값을 넘겨주어야 한다.
  • Camera.main.nearClipPlane: 카메라에서 렌더링을 시작하는 Z 축의 거리. 이 값을 사용하여 Z 축 좌표를 계산한다.

2️⃣ 카메라의 현재 위치로부터 변환한 월드 좌표로 향하는 방향 구하기

마우스 클릭으로 얻은 월드 좌표를 바탕으로, 카메라가 그 지점으로 향하는 방향 벡터를 계산한다.

Vector3 dir = mousePos - Camera.main.transform.position;
dir = dir.normalized;
  • dir: 카메라 위치에서 마우스 클릭 위치로 향하는 방향 벡터이다.
  • dir.normalized: 벡터의 크기를 1로 정규화하여 방향만을 나타낸다. 이후 이 벡터를 이용해 Raycast를 쏘게 된다.

3️⃣ 그 방향으로 Raycast 쏘기

이제, 계산된 방향을 따라 Raycast를 쏘아서 마우스로 클릭한 위치에 있는 오브젝트와 충돌하는지 확인한다.

Debug.DrawRay(Camera.main.transform.position, dir * 100.0f, Color.red, 1.0f);  // 1초 동안 광선을 그림

RaycastHit hit;
if (Physics.Raycast(Camera.main.transform.position, dir, out hit, 100.0f))
{
    Debug.Log(hit.collider.gameObject.name);  // 충돌된 오브젝트의 이름 출력
}
  • Debug.DrawRay: Camera.main.transform.position에서 dir * 100.0f까지 광선을 시각적으로 그려볼 수 있다.
  • Physics.Raycast: 광선을 쏘고, 그 방향으로 충돌한 오브젝트가 있으면 그 정보를 hit 변수에 담는다.
    • RaycastHit hit: 충돌된 오브젝트의 정보가 저장되는 변수로, hit.collider를 통해 충돌한 오브젝트의 GameObject 정보를 가져올 수 있다.

3. ScreenPointToRay

또 다른 방법으로, 마우스 위치를 화면 좌표에서 바로 Ray로 변환하는 방법도 있다.

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);  // 광선 시각화

    RaycastHit hit;
    if (Physics.Raycast(ray, out hit, 100.0f))
    {
        Debug.Log(hit.collider.gameObject.name);  // 충돌된 오브젝트의 이름 출력
    }
}
  • ScreenPointToRay: 화면 좌표를 Ray로 변환하는 함수로, 마우스 위치를 기준으로 월드 좌표로 향하는 광선을 리턴한다.
  • 이 방법은 dir 벡터를 따로 계산하지 않아도 되므로 코드가 간단해진다.

4. 투영(Projection)의 개념

게임에서 카메라는 3D 월드 공간을 2D 화면 공간투영하여 보여준다. 이를 통해 실제 3D 공간에서 일어나는 일이 화면에 나타날 수 있다.

카메라의 nearClipPlanefarClipPlane

  • nearClipPlane: 카메라의 Z 축에서 렌더링을 시작하는 거리이다.
  • farClipPlane: 카메라의 렌더링 끝 지점을 설정하는 값이다.

이 두 값은 카메라가 렌더링하는 시야의 범위를 결정한다. 예를 들어, nearClipPlane이 너무 큰 값으로 설정되면, 카메라는 너무 가까운 물체를 렌더링하지 않게 된다.


profile
李家네_공부방

0개의 댓글