본문 바로가기
개발/Unity

유니티 - 쿼터니언과 회전의 덧셈 (How to Add Two Quaternions)

by 피로물든딸기 2022. 7. 2.
반응형

Unity 전체 링크

유니티의 회전은 쿼터니언을 이용해야 한다.
인스펙터의 Rotation은 Vector3로 표현되지만 실제 타입은 Quaternion이다.
유니티가 사용자에게 보기 좋게 Vector3로 변환해 준 것이다.

Rotation은 Vector3가 아니기 때문에 Quaternion.Euler(Vector3)로 변환해야 한다.
그리고 Rotation의 값을 얻기 위해서는 rotation의 eulerAngles로 접근한다.

먼저 QuaternionTest.cs를 추가해보자.
실제 Rotation은 Vector3가 아니기 때문에 Quaternion.Euler(Vector3)로 변환한다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class QuaternionTest : MonoBehaviour
{
    void Start()
    {
        Quaternion rotation = Quaternion.Euler(new Vector3(45, 45, 0));

        this.transform.rotation = rotation;

        Debug.Log("rotation : " + this.transform.rotation);
        Debug.Log("Quaternion : " + this.transform.rotation.eulerAngles);
    }
}


아래의 그림과 같은 결과가 나온다.


로그를 보면, 실제 Inspector에 있는 Rotation은 eulerAngles로 접근해야 하는 것을 알 수 있다.


이제 회전을 더해보자.

먼저 Scene에서 X축으로 45도 회전한 후, Y축으로 45도 회전해보자.

Scene에서 마우스로 이동하기 때문에 정확히 45도로 맞추지 않고,
아래와 같이 호의 넓이로 적당히 어림짐작한다.


X축으로 45도 회전한 후, Y축으로 45도 회전하였다.


Rotation의 결과는 약 (45, 45, 0)이 된다.


이제 Y축으로 45도 회전하고, X축으로 45도 회전해보자.


결과는 약 (30, 55, 36)으로 (45, 45, 0) 이 나오지 않는 것을 알 수 있다.


두 결과를 비교하면 아래와 같다.

X를 먼저 45º 회전하고, Y를 45º 회전하는 경우 (43.5, 47.3 , 0) → 정확히 회전한 경우 : (45, 45, 0)
Y를 먼저 45º 회전하고, X를 45º 회전하는 경우 (30.3, 55.8 , 36.6) → 정확히 회전한 경우 : (30, 54.7, 35.2)

X -> Y vs Y -> X


회전은 축을 기준으로 하기 때문에 순서가 결과에 영향이 생긴다.
즉, 회전에서 X → Y ≠ Y → X 이다.


이제 수동으로 회전을 더하지 말고, 스크립트로 회전을 해보자.
아래와 같이 rotX, rotY를 정한 후, rotX → rotY와 rotY → rotX의 결과를 비교해보자.

참고로 쿼터니언을 더하면 컴파일 에러가 발생한다.

쿼터니언은 실제로 행렬 연산이기 때문에 곱셈 연산이 두 회전의 덧셈이다.

이제 코드를 수정하고 두 결과를 비교해보자.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class QuaternionTest : MonoBehaviour
{
    void Start()
    {
        Quaternion rotX = Quaternion.Euler(new Vector3(45, 0, 0));
        Quaternion rotY = Quaternion.Euler(new Vector3(0, 45, 0));

        this.transform.rotation = rotX * rotY;
        Vector3 X_Y = this.transform.rotation.eulerAngles;

        this.transform.rotation = rotY * rotX;
        Vector3 Y_X = this.transform.rotation.eulerAngles;

        Debug.Log("First X -> Y rotation " + X_Y);
        Debug.Log("First Y -> X rotation " + Y_X);
    }
}


수동으로 회전한 X → Y는 (45, 45, 0)이었으나 rotX * rotY 의 결과는 (30, 54.7, 35.2)인 것을 알 수 있다.
마찬가지로 수동 회전 Y → X는 (30, 54.7, 35.2)였지만, 결과는 (45, 45, 0)이다.


즉, X로 먼저 회전하고 싶다면 뒤에서 곱해야하는 것을 알 수 있다.

실제 올바른 코드는 아래와 같다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class QuaternionTest : MonoBehaviour
{
    void Start()
    {
        Quaternion rotX = Quaternion.Euler(new Vector3(45, 0, 0));
        Quaternion rotY = Quaternion.Euler(new Vector3(0, 45, 0));

        this.transform.rotation = rotY * rotX; // X 먼저 회전 후, Y 회전
        Vector3 X_Y = this.transform.rotation.eulerAngles;

        this.transform.rotation = rotX * rotY; // Y 먼저 회전 후, X 회전
        Vector3 Y_X = this.transform.rotation.eulerAngles;

        Debug.Log("First X -> Y rotation " + X_Y);
        Debug.Log("First Y -> X rotation " + Y_X);
    }
}


따라서 회전에서 X → Y ≠ Y → X이고 연산에서 X를 먼저 회전하기 위해서는 뒤에 곱해야 한다.

 

Unity Plus:

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Unity Pro:

 

Unity Pro

The complete solutions for professionals to create and operate.

unity.com

 

Unity 프리미엄 학습:

 

Unity Learn

Advance your Unity skills with live sessions and over 750 hours of on-demand learning content designed for creators at every skill level.

unity.com

반응형

댓글