2026-04-07 TIL (31일차)
2026-04-07 TIL (31일차)
Unreal
• World vs Local
World 좌표계
- 개념: 게임 레벨의 정중앙
(0, 0, 0)을 기준으로 한 절대적인 위치입니다.
World가 움직였다는 것의 의미
부모 액터를 잡고 월드에서 이동시키는 상황입니다.
| 구분 | 변화 여부 | 설명 |
|---|---|---|
| 부모의 월드 좌표 | 변함 | 지도상 위치가 바뀜 |
| 자식의 월드 좌표 | 변함 | 부모한테 매달려 있으니 지도상 위치가 같이 바뀜 |
| 자식의 로컬 좌표 | 그대로 | 부모라는 안에서 자식의 고유한 위치(거리)는 그대로임 |
Local 좌표계
- 개념: 나를 감싸고 있는 부모(또는 나 자신)를 기준으로 한 상대적인 위치입니다.
Local이 움직였다는 것의 의미
부모는 가만히 두고 자식 컴포넌트만 이동시키는 상황입니다. 자식을 움직이는 것은 부모에게 영향을 주지 않습니다.
| 구분 | 변화 여부 | 설명 |
|---|---|---|
| 부모의 월드 좌표 | 그대로 | 자식이 움직인다고 부모가 따라가지 않음 |
| 자식의 월드 좌표 | 변함 | 지도상에서의 최종 위치는 변함 |
| 자식의 로컬 좌표 | 변함 | 부모와의 거리가 멀어지거나 가까워짐 |
개념 정리
- World 좌표계는 GPS다: 게임 세상 전체를 관리합니다. 부모가 움직이면 자식의 GPS 값도 자동으로 바뀝니다.
- Local 좌표계는 줄자다: 부모와 나 사이의 거리입니다. 부모와 내가 같이 이동하면 줄자의 길이는 변하지 않습니다.
- 상속의 원리: 부모는 자식을 ‘끌고 다닐 권한’이 있지만, 자식은 부모를 ‘움직일 권한’이 없습니다.
언리얼 C++ 사용법
- 캐릭터 전체를 다른 곳으로 순간이동 시키고 싶다? -> 부모의 World Location 수정 (
SetActorLocation)- 캐릭터는 가만히 있고 손에 든 총만 살짝 위로 올리고 싶다? -> 자식의 Local Location 수정 (
SetRelativeLocation)
• FRotator와 FQuat (짐벌락 해결법)
FRotator(Pitch, Yaw, Roll)
| 명칭 | 축 (Axis) | 회전 방향 | 비유 |
|---|---|---|---|
| Pitch | Y축 | 위 / 아래 | 비행기가 이륙하거나 착륙할 때 코를 드는 동작 |
| Yaw | Z축 | 왼쪽 / 오른쪽 | 자동차가 핸들을 꺾어 좌회전, 우회전하는 동작 |
| Roll | X축 | 좌우 기울기 | 비행기가 비행 중 날개를 좌우로 까딱이는 동작 |
짐벌락(Gimbal Lock) 문제가 생기는 이유
짐벌락은 “세 개의 축 중 두 개의 축이 겹쳐지면서 한 방향의 회전 자유도(Degree of Freedom)를 잃어버리는 현상”
- 발생 원리:
FRotator는 3차원 회전을 한 번에 계산하지 않고,Yaw ➡️ Pitch ➡️ Roll순서대로 하나씩 차례대로 적용합니다. - 치명적인 상황: 먼저 Yaw로 좌우 방향을 잡은 뒤, Pitch를 이용해 정확히 위로 90도(수직) 꺾어버린다고 가정해 봅시다.
- 자유도 상실: 고개를 완전히 위로 든 상태에서는, 좌우로 도는 것(Yaw)과 양옆으로 비트는 것(Roll)이 완전히 동일한 회전축을 공유하게 됩니다. 즉, 3차원 공간에서 3개의 축이 필요한데 2개의 축이 하나로 합쳐져 버려서, 특정 방향으로는 아무리 수치를 바꿔도 물체가 회전하지 못하는 잠금 상태에 빠집니다.
- 결과: 이 상태에서 애니메이션이나 회전 연산을 주면 오브젝트가 기괴하게 비틀거리거나 순간적으로 화면에서 툭 끊기는 에러가 발생합니다.
해결법: 쿼터니언 (FQuat)
짐벌락을 해결하기 위해 3D 그래픽스에서 도입한 4차원 복소수 체계가 쿼터니언입니다.
원리
오일러 각도(FRotator)가 X축으로 몇 도, 다음엔 Y축으로 몇 도 순차적으로 돌리는 방식이라면, 쿼터니언은 임의의 막대기(Vector 축) 하나를 꽂고, 그 막대기를 기준으로 한꺼번에 회전시키는 방식입니다.
순서대로 축을 계산하지 않고 한 방에 회전해 버리기 때문에, 축이 겹치는 현상이 발생하지 않습니다.
- 차원: 3개의 값 대신 4개의 값($x, y, z, w$)을 사용합니다.
- 수식 형태: \(q = w + xi + yj + zk\) (여기서 $w$는 회전량(스칼라), $x, y, z$는 회전축의 벡터를 나타냅니다.)
쿼터니언 장점
- 짐벌락 해결: 축이 겹칠 일이 아예 없습니다.
- 부드러운 보간 (Slerp):
FRotator로 시작점과 끝점의 회전을 보간(Lerp)하면 중간에 숫자가 튀어 빙글 도는 현상이 생길 수 있지만, 쿼터니언은 구면 선형 보간(SLERP)을 통해 두 회전값 사이의 짧고 부드러운 경로를 찾아 매끄럽게 회전합니다. - 연산 성능 최적화: 복잡한 행렬 곱셈 연산보다 계산 속도가 빠르고 메모리도 적게 차지합니다.
• FTransform
FTransform 변수명(Rotation, NewLocation, NewScale); -> 순서로 들어간다.
• FMath::IsNearlyZero
== 0 (부동소수점 오차)
컴퓨터는 소수점을 계산하고 저장할 때 구조적인 한계로 인해 미세한 오차를 발생시킵니다.
컴퓨터 메모리 내부에서는 속도가 딱 0.0f가 아니라 0.0000014f나 -0.0000001f 같은 미세한 찌꺼기 값으로 남아있을 확률이 매우 높습니다.
이때 if (Speed == 0.0f)라고 검사하면 컴퓨터는 0이 아니라고 판단해 버립니다.
FMath::IsNearlyZero의 역할, 매개변수**
이 함수는 0에 가깝다면 0으로 인정해주는 함수입니다.
- 함수 원형:
FMath::IsNearlyZero(float Value, float ErrorTolerance = UE_KINDA_SMALL_NUMBER)Value: 0인지 검사하고 싶은 대상 숫자입니다.ErrorTolerance(오차 허용 범위): “어디까지를 0으로 인정할 것인가?”에 대한 한계치입니다.- 특징: 허용 범위의 기본값이
UE_KINDA_SMALL_NUMBER($10^{-4}$, 즉0.0001)로 세팅되어 있기 때문에, 대부분의 경우 두 번째 매개변수는 생략하고 사용해도 완벽하게 작동합니다.
This post is licensed under CC BY 4.0 by the author.