본문 바로가기

유니티/워크플로

[Unity] 트랜스폼 (2) - 회전

반응형

유니티에서의 회전과 방향

어떻게 회전을 나타낼까?

유니티는 오브젝트의 회전과 방향을 타나 낼 때 오일러 각과 쿼터니언 각 두 가지를 사용한다.

오일러 각은 우리가 흔히 사용하는 (x, y ,z) 형태이다. 반면 쿼터니언은 사원수를 사용하여 (w, x, y, z)를 사용한다.

오일러 각만 사용하면 될텐데 복잡하게 왜 쿼터니언까지 사용하는 것일까.


짐벌락 문제

오일러 각은 3차원을 3개의 축으로 회전을 나타낸다. 문제는 회전을 하다가 두 개의 축이 평행할 수(겹치게 될 수) 있다는 것이다. 이렇게 될 경우 2차원 회전으로만 가능하게 되고 더 이상 3차원 회전으로 돌아올 수 없게 된다. 이러한 현상을 짐벌락이라고 하며 3D 엔진에서는 치명적인 문제이다.

 

이를 방지하기 위해 쿼터니언(사원수)을 사용한다. 쿼터니언은 짐벌락 문제가 발생하지 않으며 모든 방향을 나타낼 수 있다. 하지만 쿼터니언은 우리에게 익숙하지 않기 때문에 유니티는 오일러 각도를 쿼터니언으로 바꿀 수 있는 여러 장치를 마련해 두었다.

 

Quaternion.Euler (함수) 오일러 각에서 쿼터니언으로 변경
quaternion.eulerAngles (프로퍼티) 쿼터니언에서 오일러 각으로 변경
//오일러각을 쿼터니언으로 변환
transform.rotation = Quaternion.Euler(Vector3.forward);

//쿼터니언을 오일러 각으로 변환
Vector3 transformRotationVector = transform.rotation.eulerAngles;

회전과 방향 관련 스크립팅

Quaternion 전역 함수

Quaternion.LookRotation(Vector3 forward, Vector3 upwards = Vector3.up)

  • 특정 벡터 방향을 쿼터니언 값으로 리턴
  • 특정 오브젝트를 바라보게 하고 싶을 때 사용
//타겟 오브젝트를 바라보도록 할 때
void Start()
{
    transform.rotation = Quaternion.LookRotation(target.position - transform.position);
}

 


Quaternion.RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta)

  • from 각도에서 to 각도까지 degree delta 만큼 회전
  • update문에서 사용하여 두 각도 사이를 부드럽게 회전하고 싶을 때 사용
void Update()
{
    transform.rotation = Quaternion.RotateTowards(transform.rotation, target.rotation, 20 * Time.deltaTime);
}

 


Quaternion.Angle(Quaternion a, Quaternion b)

  • 두 개의 쿼터니언 각도 차이를 반환
float angle = Quaternion.Angle(targetA.transform.rotation, targetB.transform.rotation);

Quaternion.AngleAxis(float angle, Vector3 axis)

  • 축(axis)을 기준으로 각(angle)만큼 회전
  • 오브젝트 자체를 회전시킬 때 유용한 함수
void Update()
{
    transform.rotation *= Quaternion.AngleAxis(180 * Time.deltaTime, Vector3.forward);
}

Quaternion.Euler(Vector3 euler)

  • 오일러 각도 값을 쿼터니언으로 변환
void Update()
{
    transform.rotation *= Quaternion.Euler(Vector3.right);
}

Quaternion.Lerp(Quaternion a, Quaternion b, float t)

  • a와 b 사이를 t만큼 보간
  • update문에서 사용하여 매 프레임마다 t만큼 보간하여 회전
  • 아래 예제는 특정 오브젝트를 부드럽게 바라보도록 한 예제
void Update()
{
    Quaternion lookTarget = Quaternion.LookRotation(target.position - transform.position);
    transform.rotation = Quaternion.Lerp(transform.rotation, lookTarget, Time.deltaTime);
}

Quaternion.Slerp(Quaternion a, Quaternion b, float t)

  • a와 b 사이를 t만큼 구의 표면 위에서 보간
  • Quaternion.Lerp는 각 값들의 수치만을 보간하는 반면 Slerp는 구의 표면을 기준으로 보간하므로 실질적인 각도 보간 기법
void Update()
{
    Quaternion lookTarget = Quaternion.LookRotation(target.position - transform.position);
    transform.rotation = Quaternion.Slerp(transform.rotation, lookTarget, Time.deltaTime);
}

Quaternion.Inverse(Quaternion rotation)

  • 매개변수로 입력된 rotation의 반대 방향을 반환

 

void Start()
{
    transform.rotation = Quaternion.Inverse(transform.rotation);
}

Quaternion.FromToRotation(Vector3 fromDirection, Vector3 toDirection)

  • fromDirection과 toDirection사이의 각도에 해당하는 쿼터니언을 반환
  • 월드 좌표계에서 특정 축이 특정 방향으로 따르도록 할 때 사용
void Start()
{
    transform.rotation = Quaternion.FromToRotation(Vector3.right, Vector3.up);
}

 


Transform 퍼블릭 함수

transform.LookAt(Transform target)

  • transform이 target transform을 바라보도록 하는 함수
  • 오브젝트를 바라보게 할 경우 Quaternion.LookRotation을 transform에 넣어주는 것과 동일한 결과 도출
void Update()
{
    transform.LookAt(target);
}

transform.Rotate(Vector3 eulers, Space relativeTo = Space.Self)

  • 여러 개로 오버로드 되어 있지만 모두 오브젝트를 특정 값만큼 회전하는 함수
  • 오브젝트를 회전할 때 가장 보편적으로 사용
void Start()
{
    transform.Rotate(target.rotation.eulerAngles, Space.World);
}

transform.RotateAround(Vector3 point, Vector3 axis, float angle)

  • point를 기준으로 angle만큼 회전 (up vector는 axis)
  • 공전하는 물체를 나타낼 때 유용
void Update()
{
    transform.RotateAround(target.position, Vector3.up, 180 * Time.deltaTime);
}

 

반응형