유니티에서 회전을 표현하는 방식에는 오일러 각(Euler Angles) 과 쿼터니언(Quaternion) 두 가지가 존재한다. 오일러 각은 사람이 이해하기 쉬운 x, y, z 축 기준의 회전값(도 단위) 을 제공하지만, 연산 과정에서 짐벌락(Gimbal Lock) 문제를 일으킬 수 있다. 반면, 쿼터니언은 네 개의 실수 (x, y, z, w) 로 구성된 4차원 복소수 형태로, 연속적인 회전 연산에 강하며 짐벌락을 방지한다.
유니티 내부에서는 모든 회전이 쿼터니언으로 처리되며, 오일러 각은 단순히 변환을 위한 인터페이스 역할을 수행한다.
쿼터니언은 다음과 같이 표현된다.
q = w + xi + yj + zk
회전은 축-각(Axis-Angle) 방식으로 정의되며, 특정 회전축 벡터와 회전 각도를 기반으로 쿼터니언 값이 계산된다.
w = cos(θ / 2)
x = ux * sin(θ / 2)
y = uy * sin(θ / 2)
z = uz * sin(θ / 2)
여기서 (ux, uy, uz) 는 회전축을 나타내는 단위 벡터이며, θ 는 회전 각도(라디안)이다.
유니티에서는 Quaternion 구조체를 통해 쿼터니언을 다룬다. 주요 메서드와 프로퍼티는 다음과 같다.
Quaternion.identity
회전이 없는 단위 쿼터니언 (0, 0, 0, 1)
Quaternion.Euler(Vector3 eulerAngles)
오일러 각을 쿼터니언으로 변환
Quaternion.AngleAxis(float angle, Vector3 axis)
특정 축과 각도를 기반으로 회전 생성
Quaternion.LookRotation(Vector3 forward, Vector3 up)
주어진 방향 벡터를 바라보도록 회전 생성
Quaternion.Slerp(Quaternion a, Quaternion b, float t)
두 회전 사이를 구면선형보간(Spherical Linear Interpolation)
짐벌락 방지
오일러 각 방식에서 발생하는 회전 자유도 손실 문제를 방지한다.
부드러운 회전 보간
Slerp 연산을 통해 균일한 속도로 회전 보간이 가능하다.
누적 회전 처리에 강함
여러 회전을 연속적으로 적용할 때도 수치 안정성이 높다.
직접 값을 수정하지 말 것
쿼터니언의 (x, y, z, w) 값을 임의로 수정하면 회전이 깨질 수 있다. 반드시 제공되는 메서드를 사용하여 생성하거나 수정해야 한다.
Euler 변환 최소화
잦은 쿼터니언 ↔ 오일러 변환은 부동소수점 오차를 누적시킬 수 있다.
정규화 유지
회전 연산을 여러 번 수행하면 길이가 1이 아닌 쿼터니언이 될 수 있으므로 필요 시 Normalize 처리해야 한다.
쿼터니언은 유니티에서 안정적이고 정확한 회전을 구현하기 위한 핵심 수학적 구조이다. 비록 직관적으로 이해하기 어렵지만, 오일러 각의 한계를 극복하고 부드러운 회전을 구현할 수 있다는 점에서 필수적으로 숙지해야 한다. 실무에서는 오일러 각을 입력값으로 사용하되, 내부 회전 연산과 보간에는 쿼터니언을 사용하는 것이 일반적이다.