Unityの回転はZXYの順で適用したものだというお話

オイラー角で入力された回転値は、内部的にQuaternionに変換されます。
その際に各軸のQuaternionを掛ける順番が異なると結果が異なるという話と、適用順はZXYであるという話です。

Unity2017.4.1

回転Quaternionの作り方

まず、Transformのインスペクタに表示されているものは、XYZそれぞれの軸に対する回転量です。
この値は回転をQuaternionではなくオイラー角を表しています。

f:id:halya_11:20190124221118p:plain

内部的には、回転はQuaternionで表されます。
今回はこのQuaternionをオイラー角から自前で作ってみます。

まずは各軸に対する回転をQuaternionで表し、これをQx, Qy, Qzとします。
これらを掛け合わせて回転をあらわすQuaternionをつくるわけですが、
回転させる順番が異なれば結果が異なるので、掛け合わせる順番に気をつけなければなりません。

Unityの場合、回転のQuaternionはQz -> Qx -> Qyの順で適用することで計算します。

確認

上記の内容をスクリプトを書いて確認してみます。

using UnityEngine;



public class RotationExample : MonoBehaviour 

{

    public enum RotationType

    {

        ZXY,

        ZYX

    }


    [SerializeField, Range(-180, 180)]

    private float _x;
    [SerializeField, Range(-180, 180)]

    private float _y;
    [SerializeField, Range(-180, 180)]

    private float _z;

    [SerializeField]

    private RotationType _type;



    private void Update ()

    {

        // X軸回転

        var rotX    = Quaternion.AngleAxis(_x, new Vector3(1, 0, 0));

        // Y軸回転

        var rotY    = Quaternion.AngleAxis(_y, new Vector3(0, 1, 0));

        // Z軸回転

        var rotZ    = Quaternion.AngleAxis(_z, new Vector3(0, 0, 1));

        var quaternion    = Quaternion.identity;

        if (_type == RotationType.ZXY) {

            quaternion        = rotY * rotX * rotZ;

        }

        else if (_type == RotationType.ZYX) {

            quaternion        = rotX * rotY * rotZ;

        }

        transform.rotation    = quaternion;

    }

}

ZXYとZYXのパターンを作って挙動を比較します。
ちなみに上記のソースコードの通り、UnityのQuaternionは先に適用したいものほど右に書いて掛け合わせます。

これを再生すると次のようになります。
ZXYの時にTransformのRotationと指定したオイラー角の値が一致していることが確認できます。

f:id:halya_11:20190124223415p:plain

ZYXにすると回転の値が一致しません。

f:id:halya_11:20190124223433p:plain

参考

docs.unity3d.com