반응형

유니티 엔진을 사용하면서 항상 '오브젝트를 움직여야하는 경우에 어떤 방법으로 오브젝트의 움직임을 제어해야 하는가?' 하는 고민을 해왔다.

 

 

Transform? Rigidbody?

만약 Transform을 사용하려 해도 Position, LocalPosition, Translate 등 방법이 더 다양하게 있었고 Rigidbody 또한 AddForce, MovePosition 등 여러 가지의 방법들이 존재했다. 그래서 개념 정리를 위해 이 부분들을 다뤄보려 한다. 생각보다 정리해야 하는 내용들이 많아서 Rigidbody에 대한 정리는 다음 포스팅에 이어 가려 한다.

 


Transform?

'Transform' 이라는 컴포넌트를 사용해서 움직이는 방법을 알아보기 전에 'Transform' 이라는 컴포넌트 그 자체에 대해 먼저 알아보자.

https://docs.unity3d.com/kr/2021.3/Manual/class-Transform.html

 

 

먼저 'Transform' 컴포넌트는 'Inspector' 창에서 보이는 것처럼 Position(위치), Rotation(회전), Scale(크기)를 제어하는 기능을 갖고 있다. 또한 'Inspector' 창에서는 보이지 않지만 오브젝트 간의 '부모-자식' 관계의 상태를 저장하고 있기도 하다. 그래서 실제로 'MonoBehaviour'에서 보면 오브젝트의 '부모-자식' 관계를 제어하는 기능은 'Transform' 클래스 안에 존재한다.

 

'transform'의 부모 오브젝트를 설정하는 'SetParent()'

이처럼 'Transform' 컴포넌트는 Scene에 존재하는 오브젝트의 필수적인 요소들을 갖고 있기 때문에 Scene에 존재하는 오브젝트가 'Transform' 컴포넌트를 갖고 있지 않는 상태는 불가능하다. 굳이 따지면 2D를 위한 'Canvas' 안의 오브젝트들은 갖고 있지 않을 수 있지만 이 또한 'RectTransform' 이라는 2D 오브젝트의 'Transform'을 필수로 갖고 있어야 하기 때문에 사실상 다르지 않다.

 

결과적으로 'Transform' 컴포넌트는 Scene에 존재하기 위한 필수 컴포넌트이며, 오브젝트의 위치, 회전, 크기를 제어하는 기능을 수행한다.

 

 

Transform.Position()

'Transform' 이라는 컴포넌트에 대해서도 알아봤으니 이제 이를 이용한 오브젝트 움직임을 구현하는 방법 중 하나인 'Position()'에 대해 먼저 살펴보도록 하자.

https://docs.unity3d.com/kr/530/ScriptReference/Transform-position.html

 

Transform-position - Unity 스크립팅 API

The position of the transform in world space.

docs.unity3d.com

 

tr은 움직이려는 오브젝트의 'Transform' 컴포넌트이다.

앞으로 설명할 다른 방법들도 마찬가지지만, 이미 친절하게 설명이 적혀져있다.

여기서 월드 좌표라는 말이 나온다. 이에 대한 것 까지 다루기에는 너무 번잡해질 것 같아서 간단하게만 설명하고 넘어가자면, 유니티에서는 Global 좌표와 Local 좌표가 존재하는데 'Global 좌표는 Scene 공간에서의 좌표'이고 'Local 좌표는 Scene 공간에서 해당 오브젝트의 상대적인 좌표' 이다. 글로 보면 헷갈릴 수도 있지만 실제로 다뤄보면 굉장히 직관적으로 확인할 수 있으니, 이해가 잘 되지 않는다면 직접 만져보며 차이를 느끼는 걸 적극 권장한다.

유니티 Scene View에 지구 모양의 아이콘을 눌러보면 좌표계를 변경할 수 있다. 기본으로는 Global로 설정되어 있다.

다시 돌아오자면 월드 좌표 = Global 좌표이고, Position()을 통해 오브젝트를 움직여보면 월드 기준의 XYZ로 움직이는 걸 확인할 수 있다.

Position()을 사용한 이동

앞으로의 예시들도 동일하게 Cube 오브젝트의 빨간 부분이 Cube의 앞을 표현한 것 이다.

Cube 오브젝트는 오른쪽으로 회전되어 있지만 'Position()'은 월드 좌표. 즉 Scene에서의 XYZ를 기준으로 움직이기 때문에 움직이는 오브젝트의 회전 상태와는 무관하게 움직인다.

 

 

Transform.localPosition()

다음으로는 'localPosition()'을 사용한 움직임이다. 

localPosition()

이 또한 친절하게 적혀있지만 실제로 실행시켜보면 조금 혼란스러울 수 있다. 간단하게 설명하자면, 자신의 부모 오브젝트 기준의 XYZ를 따른다. 만약 움직이려는 'tr'의 부모 오브젝트가 존재하고, 그 부모 오브젝트가 45도 만큼 오른쪽으로 회전되어 있다면 부모 오브젝트의 정면은 45도 만큼 오른쪽으로 회전되어있는 방향을 가리키게 되므로 그 방향을 향해 움직인다. 설명에 적혀있는 '상대적'이 이것을 뜻한다.

 

localPosition 움직임 중 부모 오브젝트의 Y 값을 움직이면 이처럼 부모 오브젝트의 정면이 향하는 곳을 기준으로 이동하는 걸 확인할 수 있다.

 

 

Transform.Translate()

마지막으로 'Translate()'을 사용한 방법이다. 어떻게 보면 이게 가장 생각할 일 적은 방법이라고 느낄 수 있다.

Translate()

이 방법으로 움직이게 되면 움직이려는 오브젝트의 XYZ를 기준으로 움직이는 방식이다. 부모 오브젝트나 Global, Local 좌표 이런 복잡한 것과 상관없이 움직이게 하고 싶다면 가장 간단하게 생각할 수 있다.

 


 

마치며

왜 움직이는 방법이 여러 가지이며, 왜 좌표는 여러 개이고, 언제 어떤 걸 사용해야 하는지 궁금할 것이다. 하지만 이 문제에 대해서는 절대적인 정답은 없다. 개발하는 나 자신이 어떤 식으로 움직이기를 원하는지에 따라 사용하기 나름이기 때문이다. 예를 들어 총을 든 캐릭터의 총구에서 총알이 나가게 하고 싶다면 총의 방향을 기준으로 앞을 향해 움직여야 할 것이고, 캐릭터의 주변을 오브젝트가 계속해서 돌게 만들고 싶다면 캐릭터 오브젝트가 어딜 향하고 있던 무관하게 움직이게 만들어야 하고, 또 어떤 경우에는 부모 오브젝트의 위치를 기준으로 원하는 방향으로 움직이게 하고 싶을 수도 있기 때문이다.

나도 처음 접했을 때는 어떤 경우에 어떤 걸 사용해야 하는지 헷갈려서 시행착오를 겪으며 익혔던 기억이 있다. 더군다나 지금 소개한 경우에는 3D 좌표이고 2D에서 사용하게 되면 생각한 것과 또 다르게 움직일 수도 있다. 때문에 정확하게 이해하는 것도 중요하지만 실제로 구현해서 어떻게 움직이는지 보고 느끼는 게 가장 좋은 방법이 아닐 까 싶다.

 

간단해보이지만 생각보다 정리할 게 많았던 'Transform을 이용한 움직임'이였다. 다음엔 Rigidbody를 이용한 움직임에 대해 알아보고 또 어떤 차이가 있는지에 대해 정리해야겠다.

반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기