1. 개요
최근에 폰을 이용해서 캐릭터의 움직임을 구현하게 되었다. 그런데 그 과정에서 AddMovementInput 함수를 쓰지 않고 AddWorldOffset 함수나 AddActorLocalOffset를 이용해서 폰을 움직여야 한다는 제약사항이 있었다. 원래 AddMovementInput을 사용할 때는 연결된 컨트롤러의 입력을 받아서 그대로 방향벡터와 함께 넘겨주기만 하면 되었지만, 처음에 AddActorLocalOffset와 GetActorForwardVector를 사용해서 폰을 이동시키려고 했더니 자꾸 회전한 후에는 원하는 방향으로 움직이지 않고 이상한 움직임이 보여서 애를 먹었다. 뭔가 이상하다 싶어 함수들에 관해 좀더 자세히 찾아보니 월드 좌표계와 로컬 좌표계의 차이를 알지 못했기 때문에 발생한 불상사였다. 그렇기 때문에 이번 글에서는 월드 좌표계와 로컬 좌표계에 대해 정리해 보려 한다.
2. 월드 좌표계 vs. 로컬 좌표계
1. 월드 좌표계
월드가 중심이 되는 절대적인 좌표계
- 월드 좌표는 (0,0,0) 지점에서 시작 ㅡ> (0,0,0)이 월드의 원점
- 레벨 내에 배치된 모든 객체들의 위치와 회전이 월드 좌표계를 기준으로 정의
- 고정된 좌표계 ㅡ> 액터가 이동하거나 회전해도 변화 X
2. 로컬 좌표계
객체의 중심이 원점이 되는 상대 좌표계
- 객체가 중심 ㅡ> 객체가 이동, 회전하면 로컬 좌표계도 함께 변화
- 객체의 내부 컴포넌트나 자식 객체의 위치, 회전을 정의할 때 용이
3. 내가 겪은 문제
내가 겪은 문제는 이렇게 알아보고 난 뒤에는 당연하다 싶은 문제였다.
우선 결론부터 얘기하자면, GetActorForwardVector() 함수가 반환하는 앞쪽 방향 벡터는 월드 좌표계를 기준으로 하는 벡터였고 나는 이 벡터를 이용해서 아래와 같은 코드를 작성해서 폰을 움직이려 했기 때문에 에러가 발생했다.
FVector ForwardVector=GetActorForwardVector();
AddActorLocalOffset(ForwardVector * AxisValue * MoveSpeed * SpeedMultiplier * GetWorld()->GetDeltaSeconds(), true);
그냥 봐서는 뭐가 크게 문제인지 모를 수 있다. 하지만 월드 좌표계와 로컬 좌표계의 차이를 알게 되었으니 이에 대해 생각해보면, 내가 ForwardVector에 저장한 값은 GetActorForwardVector()로 얻은 월드 좌표계 기준으로 액터가 바라보는 앞 방향을 나타내는 벡터이다. 그런데 내가 액터를 움직이기 위해 사용한 함수는 AddActorLocalOffset()으로 이 함수는 앞으로 가고 싶다면 ForwardVector를 월드 좌표계 기준으로 받아올 필요 없이 그저 아래 코드처럼 FVector(1,0,0)으로 바꿔주면 액터 기준으로 앞 방향으로 이동하게 만들 수 있다.
AddActorLocalOffset(FVector(1,0,0) * AxisValue * MoveSpeed * SpeedMultiplier * GetWorld()->GetDeltaSeconds(), true);
만약 내가 월드 좌표계 기준의 액터의 방향 벡터를 받아와 사용하려고 한다면 아래 코드처럼 AddActorWorldOffset() 함수를 사용하면 된다.
FVector ForwardVector = GetActorForwardVector();
AddActorWorldOffset(ForwardVector * AxisValue * MoveSpeed * SpeedMultiplier * GetWorld()->GetDeltaSeconds(), true);
4. 정리
월드 좌표계와 로컬 좌표계에 대해 알아보기 전에는 로직적으로는 내가 생각하기에 전혀 이상이 없는데 폰의 이동이 회전만 했다하면 이상하게 이루어지니 도통 어느 부분이 문제인지 알 수가 없었다. 그러다 AddActorWorldOffset, AddActorLocalOffset 으로 함수가 나뉘어 있는 이유가 있지 않나 싶어 이에 대해 검색해보니 그제서야 '아..... 이러니 당연히 안되지' 라는 생각이 들었다. 뭐가 문제인지를 모르니 엄한 부분만 고치면서 시간을 허비하기도 했는데 뭐 결국은 함수가 어떤 좌표계를 기준으로 동작을 처리하는지에 대해 확실히 알 수 있는 기회이기도 했다. 덕분에 앞으로도 잊어 먹지는 않을 것 같다.
* 추신 : 앞으로 함수를 사용하기 전에는 함수의 동작 방식에 대해 자세히 알아보는 습관을 들이는 것이 시간을 절약하는 방향일 것 같다.
참고자료
https://willeeproject.tistory.com/743500
👨💻 [Unreal] 언리얼 엔진 5 에서 공간 좌표의 종류와 특징은 어떻게 되나요?
👨💻 안녕하세요, 윌리 프로젝트의 윌리 입니다.언리얼 엔진 5 에서 공간 좌표의 종류와 특징은 어떻게 되는지 물어봤습니다.질문 >언리얼 엔진 5 에서 공간 좌표의 종류와 특징은 어떻게 되
willeeproject.tistory.com
https://heesun9113.tistory.com/345?utm_source=chatgpt.com
[Unreal/BluePrints] 벡터이론, 로컬 좌표와 월드 좌표
인프런에서 rookiss [입문자를 위한 UE5] Part1. 언리얼 엔진 블루프린트 강의를 듣고 정리한 글입니다. 벡터이론 벡터 : 방향 + 크기 정규화를 한다 → 단위 벡터로 만든다 로컬 좌표와 월드 좌표 지
heesun9113.tistory.com
'언리얼엔진(UE)' 카테고리의 다른 글
[UE] 타이머 사용 시 유의 사항과 해결방법 (0) | 2025.02.12 |
---|---|
[UE] TSubclassOf<>와 TSoftClassPtr<> (0) | 2025.02.07 |
[UE] 액터 생애주기(Actor Life Cycle) (0) | 2025.02.05 |
[UE] Lerp (선형 보간, Linear Interpolation) (0) | 2025.02.04 |
[UE] Tick, DeltaTime (0) | 2025.02.03 |