유니티에서 오브젝트를 회전할 때 자주 사용하는 transform.Rotate와 Quaternion.Euler에 대해 깊게 알아보고, 차이점을 알아보자.
요약
transform.Rotate는 현재 상태에서 해당 오일러 각만큼 회전시키는 것이고,
Quaternion.Euler는 현재 상태를 해당 오일러 각으로 회전시키는 것이다.
매개변수
transform.Rotate와 Quaternion.Euler의 매개변수는 간단하게 보면 다음과 같다.
transform.Rotate(Vector3 eulerAngles);
Quaternion.Euler(Vector3 eulerAngles);
Vector3를 대신해서 float x, float y, float z값도 인자로 넣을 수 있다.
Rotate 함수의 인자에는 한 가지 추가로 들어갈 수 있는데,
자신의 좌표축을 중심으로 회전할지, 월드의 좌표축을 중심으로 회전할지 선택하는 것이다.
transform.Rotate(Vector3 eulerAngles, Space relativeTo);
Space의 Default 값은 자신이다. (Space.Self)
위는 Y축 기준으로 45도 회전한 두개의 큐브를 Y축 상단에서 바라봤을 때, Z축을 중심으로 회전시킨 결과이다.
좌측 큐브는 Rotate의 인자에 Space.Self를 넣었고, 우측 큐브는 Space.World를 넣었다.
transform.Rotate(0f, 0f, 1f, Space.Self);
transform.Rotate(0f, 0f, 1f, Space.World);
우측 상단을 보면 현재 좌표축이 나오는데, 해당 좌표축이 World의 좌표축이다.
큐브는 회전되었지만, World는 회전되지 않았으므로, World의 Z축은 사진과 같이 큐브의 모서리를 관통한다.
하지만 Self의 기준으로는, Y축 기준 좌측으로 45도 회전하였기에 좌표 축도 같이 바뀌는 모습이다.
사용법
transform.Rotate는 반환값이 없기 때문에 그냥 쌩으로 사용하면 된다.
transform.Rotate(0f, 90f, 0f);
Vector3 vector = new Vector3(0f, 90f, 0f);
transform.Rotate(vector);
현재 상태에서 Y축(Yaw)을 중심으로 90도를 더 회전시킨다는 뜻이다.
유니티 공식 문서에 따르면 Z축, X축, Y축 순으로 회전시킨다고 한다.
Quaternion.Euler는 Quaternion을 반환값으로 가지고 있다.
Quaternion은 오일러 각의 문제점인 짐벌락(Gymbal lock)이 해결된 3차원 회전 방법인데,
오일러 각인 Vector3를 넣어주면 Quaternion으로 변환을 시켜주는 것이다.
따라서 같은 Quaternion형인 transform.rotation에 넣어주어야 한다.
transform.rotation = Quaternion.Euler(0f, 90f, 0f);
Vector3 vector = new Vector3(0f, 90f, 0f);
transform.rotation = Quaternion.Euler(vector);
현재 회전값을 X축 0, Y축 90, Z축 0으로 회전시킨다는 뜻이다.
이 역시 유니티 공식 문서에 따르면 Z축, X축, Y축 순으로 회전시킨다고 한다.
설명
1. Pitch - Yaw - Roll
(출처 : https://en.wikipedia.org/wiki/Aircraft_principal_axes)
날개에서 날개로 이어지는 축을 중심으로 Pitch (1, 0, 0)
Vector3.left, Vector3.right에 해당
기수(앞) 위에서 아래로 이어지는 축을 중심으로 Yaw (0, 1, 0)
Vector3.up, Vector3.down에 해당
기수(앞)에서 꼬리까지 이어지는 축을 중심으로 Roll (0, 0, 1)
Vector3.forward, Vector3.back에 해당
2. 짐벌
(출처 : https://ko.wikipedia.org/wiki/%EC%A7%90%EB%B2%8C)
짐벌은 하나의 축을 중심으로 물체가 회전할 수 있도록 만들어진 구조물이다.
위의 사진은 세 개의 짐벌이 하나로 구성되어있다.
각각의 짐벌은 Roll, Pitch and Yaw를 중심으로 이루어져 있으며 자유도를 가진다.
3. 짐벌락
(출처 : https://en.wikipedia.org/wiki/Gimbal_lock)
두번째 종속된 각으로 인해 첫번째와 세번째의 각이 일치하게 되는 순간, 첫번째와 세번째는 동일한 회전을 하게 된다.
즉, 하나의 회전 각이 소실되는 현상을 말한다.
실험을 통한 이해 Ⅰ
현재 2개의 큐브의 Rotation.y 값을 45로 맞춰두고, 각각 다른 회전 방법을 지닌 스크립트가 포함시켰다.
각 스크립트는 다음과 같다.
public class Rotate : MonoBehaviour
{
void Start()
{
transform.Rotate(0f, 45f, 0f);
}
}
public class Euler : MonoBehaviour
{
void Start()
{
transform.rotation = Quaternion.Euler(0f, 45f, 0f);
}
}
실행시킨 결과는 다음과 같다.
Rotate 큐브는 Rotation.y 값이 기존 45에 Rotate의 45가 더해져 90이 되었고,
Euler 큐브는 Rotation.y 값이 바뀌지 않았다.
실험을 통한 이해 Ⅱ
이해 1과 동일한 큐브를 Rotation 값만 초기화 시킨 뒤,
각 스크립트의 Start 함수를 Update 함수로 변경 후, 각 인자를 (0f, 1f, 0f)로 변경하였다.
각 스크립트는 다음과 같다.
public class Rotate : MonoBehaviour
{
void Update()
{
transform.Rotate(0f, 1f, 0f);
}
}
public class Euler : MonoBehaviour
{
void Update()
{
transform.rotation = Quaternion.Euler(0f, 1f, 0f);
}
}
실행시킨 결과는 다음과 같다.
Rotate 큐브는 Y축을 기준으로 끊임없이 회전하고,
Euler 큐브는 Rotation.y 값이 1인 상태로 멈추었다.
번외
Quaternion은 float x, float y, float z, float w로 이루어져 있으나, 해당 x, y, z는 오일러 각의 x, y, z와는 다르니 주의해야한다.
즉, transform의 회전값을 불러와 작업을 해야한다면
transform.rotation.eulerAngles 함수로 오일러 각을 불러오면 된다.
public class Rotate : MonoBehaviour
{
void Update()
{
transform.Rotate(0f, 1f, 0f);
}
}
public class Euler : MonoBehaviour
{
[SerializeField] Transform RotateCube;
void Update()
{
transform.rotation = Quaternion.Euler(RotateCube.rotation.eulerAngles);
}
}
Rotate 스크립트는 그대로 두고, Euler 스크립트만 위와 같이 변경하였다.
실행 결과는 다음과 같다.
Euler 큐브가 Rotate 큐브를 따라서 회전하는 모습을 확인할 수 있다.
개인 공부용 포스팅인 점을 참고하시고, 잘못된 부분이 있다면 댓글로 남겨주시면 감사드리겠습니다.