Chapter 8. 로컬 좌표계와 월드 좌표계

개발하는 운동인·2024년 11월 21일

⭐ 원점(Origin)

  • 유니티를 비롯한 대부분의 게임 엔진에서는 오브젝트의 위치와 방향을 나타내기 위해 좌표계를 사용합니다. 유니티에서는 기본적으로 x축(좌우), y축(높낮이), z축(앞뒤)으로 이루어진 3차원 직교 좌표계를 사용합니다.

  • 현실에서 물체의 위치를 나타내기 위해서는 기준점이 필요합니다. 예를 들어, "내 오른쪽 1m 거리에 공이 있어"라고 말할 때, "나"라는 기준점을 사용합니다. 하지만 상대방이 나로부터 4m 떨어진 곳에 있다면, "네 왼쪽 3m 거리에 공이 있어"라고 설명하는 것이 상대방이 공의 위치를 더 쉽게 파악할 수 있습니다. 이때 기준이 되는 위치를 원점(Origin)이라고 합니다.

⭐ 월드 좌표계

  • 유니티에서도 원점을 기준으로 각 축 방향으로의 거리를 통해 오브젝트의 위치를 결정합니다. 이때 모든 축의 방향이 0인 (0, 0, 0)을 원점으로 하여 물체의 위치나 방향 등을 표현하는 것을 월드 좌표계(World Coordinate System)라고 합니다.
  • 월드 좌표계에서 기술된 위치를 월드 포지션(World Position) 또는 절대 위치(Absolute Position)라고 합니다. 예를 들어, 원점으로부터 왼쪽으로 2m 떨어진 곳에 있는 공의 위치는 (-2, 0, 0), 오른쪽으로 3m 앞으로 2m 떨어져있고 5m 높은 곳에 있는 공은 (3, 5, 2)라고 표현할 수 있습니다.

✅ 하지만 해당 오브젝트가 부모 오브젝트가 있냐 없냐에 따라 달라진다.

  • 부모 오브젝트가 있는 A 오브젝트 vs 부모 오브젝트가 없는 B 오브젝트가 있다고 해보자. 먼저,

🤔 B 오브젝트의 트랜스폼의 위치를 (1,2,3)의 좌표로 만들고 싶을 때 코드로 표현하면 어떻게 될까?

  • B 오브젝트는 부모 오브젝트가 없으므로, 그대로 new Vector3(1,2,3); 을 사용하면 된다.
public GameObject BObject; 
void Start()
{
	BObject.transform.position = new Vector3(1,2,3); 
}

🤔 A 오브젝트의 트랜스폼의 위치를 (1,2,3)의 좌표로 만들고 싶을 때 코드로 표현하면 어떻게 될까?

  • 두가지로 나뉜다.
      1. A 오브젝트의 부모 오브젝트가 원점(0,0,0)에 위치한다.
public GameObject AObject; 
void Start()
{
	AObject.transform.position = new Vector3(1,2,3); 
}
    1. A 오브젝트의 부모 오브젝트가 EX) (1,1,1)에 위치한다.
public GameObject AObject; 
void Start()
{
	AObject.transform.position = new Vector3(0,1,2); 
}
  • 1,2에 코드는 다르지만 같은 위치를 갖는다. 1번에서 A 오브젝트는 부모 오브젝트가 없으므로 월드 좌표계를 이용한 것이고, 2번에서 A오브젝트는 부모 오브젝트가 있으므로 부모 오브젝트의 좌표계를 이용했다. 즉, 로컬 좌표계를 사용한 것이다.

✅ 로컬좌표 또는 월드좌표 구하는 공식

⭐ transform.position

  • transform.position은 Transform 컴포넌트의 위치를(x,y,z) 나타내는 월드 좌표계이다.

⭐ AObject.transform.position

  • AObject.transform.position은 AObject의 Transform 컴포넌트의 위치를(x,y,z) 나타내는 월드 좌표계이다.

⭐ AObject.transform.localPosition

  • AObject.transform.position은 AObject의 부모 오브젝트 Transform 컴포넌트의 위치를(x,y,z) 고려한 로컬 좌표계이다.

  • 만약 실수로, AObject.transform.localPosition 코드를 작성하였지만, 부모가 없을 때는 월드 좌표계로 계산된다.

  • 아래 코드 예제를 보자.

public GameObject AObject;

void Start()
{
    // 부모가 없으므로 AObject는 월드 좌표와 로컬 좌표가 동일합니다.
    
    // AObject의 로컬 좌표를 (2, 3, 4)로 설정
    AObject.transform.localPosition = new Vector3(2, 3, 4);
    
    // AObject의 월드 좌표를 출력
    Debug.Log("AObject's World Position: " + AObject.transform.position); // (2, 3, 4)
}

🤔 부모 오브젝트가 있는 A 오브젝트의 위치를 3,3,3으로 변경하고 싶다면? 부모 오브젝트의 위치는 원점이다.

public class AObject : MonoBehaviour //AObject가 가지고 있는 스크립트
{
	void Start()
    {
    	GameObject Parent = GameObject.Find("Parent);
        Parent.transform.position = new Vector3(0,0,0); //부모의 월드 좌표를 0,0,0으로 설정
        
    	transform.localPosition = new Vector3(3,3,3); //부모의 월드 좌표를 기준으로 AObject의 로컬 좌표를 3,3,3으로 설정. 
        
        Debug.Log(transform.position); //3,3,3으로 변경 
     }
 }

🤔 부모 오브젝트가 있는 A 오브젝트의 위치를 3,3,3으로 변경하고 싶다면? . 단 부모 오브젝트의 위치를 변경할 수 없고 부모의 위치는 (2,1,1)로 고정되어 있다.

public class AObject : MonoBehaviour //AObject가 가지고 있는 스크립트
{
	void Start()
    {
    	GameObject Parent = GameObject.Find("Parent);
            
    	transform.localPosition = new Vector3(3,3,3) - Parent.transform.position; //(3,3,3) - (2,1,1) = (1,2,2). 즉, A오브젝트의 로컬 좌표는 (1,2,2) 이다. 
        
        Debug.Log(transform.position);   //3,3,3 출력
     }
 }

🤔 어떻게 해서 transform.localPosition이 1,2,2 이지만, transform.position이 3,3,3이 나왔을까?

  • transform.localPosition은 월드 기준 좌표가 아닌 부모 기준 좌표이다. 즉, 부모의 위치에 따라 좌표가 달라진다. 상대적인 성격이 있다.
  • Unity에서 transform.localPosition을 설정하면, 이는 객체의 로컬 좌표계에서의 위치를 설정하는 것이며, Unity 엔진은 이를 자동으로 월드 좌표계로 변환하여 transform.position을 업데이트 한다.

✅ 월드 좌표 계산 방식

    1. transform.localPosition 의 값을 구한다
    1. Unity에서 transform.localPosition의 값을 부모 객체의 월드 좌표계에 맞게 변환하여 transform.position을 계산한다.
    1. 즉, Debug.Log(transform.position); 을 하여 transform.position의 값을 나타낼 때 부모의 위치를 고려하여 계산한다. 위 코드에서 부모의 위치는 (2,1,1)이였다.
  • 최종적으로 transform.position 을 나타낼 때 부모 월드 좌표와 자신의 로컬 좌표를 더한다.
  • 목표 월드 좌표(transform.position) = 목표 로컬 좌표(transform.localPosition) + 부모 월드 좌표(Parent.transform.position)

🤔 부모 오브젝트가 없는 A 오브젝트의 위치를 3,3,3으로 변경하고 싶다면?

public class AObject : MonoBehaviour //AObject가 가지고 있는 스크립트
{
	void Start()
    {
    	transform.position = new Vector3(3,3,3); 
         Debug.Log(transform.position); //3,3,3으로 변경
     }
 }

벡터

3D 게임에서, 카메라 위치를 플레이어 뒷쪽에 위치 시키려면 어떻게 해야 할까? 단, 카메라는 플레이어의 자식 오브젝트이다.

    1. 카메라는 플레이어의 자식이므로 카메라의 위치를 변경할 때 플레이어 기준으로 위치를 업데이트해야 한다. 즉, 로컬 좌표계를 사용한다.
public class Player : MonoBehaviour 
{
	public Camera cam;
	 void Start()
     {
    	cam.transform.localPosition = -transform.forward * 3.0f + Vector3.up * 1.5f;
     }
 }

0개의 댓글