WisdomSoft - for your serial experiences.

四元数

3次元空間上の軸に対する回転量を四元数を用いて表現できます。

回転を表現する

オブジェクトの向きや回転における角度は Unity ツール(Inspertor)上ではオイラー角が使われています。オイラー角は 3D 空間上の X 軸、Y 軸、Z 軸それぞれの角度を指定することで方向を表します。スクリプトでは Vector3 型で表現でき、私たち人間にとって直感的で扱いやすいデータです。しかし、オイラー角にはジンバルロックと呼ばれる難しい問題が付きまといます。

そこで、多くの 3D グラフィックス API と同じように、Unity では四元数を用いて角度を表現します。スクリプトからオブジェクトの角度を指定するには UnityEngine.Quaternion 構造体を利用する方法が一般的です。

UnityEngine.Quaternion 構造体
public struct Quaternion

この構造体のコンストラクタはオーバーロードされており、各要素を初期化する値を指定できます。

Quaternion 構造体のコンストラクタ
public Quaternion(float x, float y, float z, float w)

x パラメータには X 要素の値を、y パラメータには Y 要素の値を、z パラメータには Z 要素の値、w パラメータには W 要素の値を、それぞれ指定します。

各要素の値はフィールドで公開されています。X 要素の値は x フィールドから、Y 要素の値は y フィールドから、Z 要素の値は z フィールドから、W 要素の値は w フィールドから設定または取得できます。

Quaternion 構造体 x フィールド
public float x
Quaternion 構造体 y フィールド
public float y
Quaternion 構造体 z フィールド
public float z
Quaternion 構造体 w フィールド
public float w

構造体のメンバだけを見ると Vector4 構造体との違いがないため Quaternion 構造体の役割に疑問を持つかもしれません。ここで四元数の詳細は割愛しますが、Quaternion 構造体はベクトルではなくベクトルの回転を表現するものであり、その性質は複素数学と深い関係があります。

コード1
using UnityEngine;

public class Test : MonoBehaviour
{
    void Start()
    {
        Quaternion q = new Quaternion(0, 0, 0, 1);
        print("q=" + q);
    }
}
実行結果
コード1 実行結果

コード1はコンストラクタで初期化した Quaternion 構造体の値を出力しています。単にフィールドの値を出力しただけでは四元数の役割を理解することは難しいかもしれません。

オイラー角との変換

Quaternion 構造体は四元数を表しているため、フィールドの値はオイラー角のように単純に角度を保存するものではありません。多くの人にとって、四元数の値が表す回転は直感的なものではないでしょう。四元数からオイラー角を求める、またはその逆を行うには、オイラー角との変換を計算しなければなりません。

Unity では Quaternion 構造体がオイラー角との変換処理を行う機能を提供しています。オイラー角を表す 3 次元ベクトルから四元数を生成するには Euler() メソッドを使います。

Quaternion 構造体 Euler() メソッド
public static Quaternion Euler(float x, float y, float z)
public static Quaternion Euler(Vector3 euler)

Euler() メソッドは Quaternion 構造体の静的メソッドで、オイラー角から対応する Quaternion 構造体の値を生成してくれます。

もしくは eulerAngles プロパティを通すことで Quaternion 構造体の値に対してオイラー角の値で設定または取得ができます。

Quaternion 構造体 eulerAngles プロパティ
public Vector3 eulerAngles { get; set; }

もちろん四元数とオイラー角の変換には計算コストがかかるため、アニメーションの処理といった連続して値が更新されるコードではオイラー角との変換は避け、四元数のみを使うべきでしょう。

コード2
using UnityEngine;

public class Test : MonoBehaviour
{
	void Start()
	{
		Quaternion q = Quaternion.Euler(45, 90, 180);
		print("q=" + q);
		print("X=" + q.eulerAngles.x);
		print("Y=" + q.eulerAngles.y);
		print("Z=" + q.eulerAngles.z);
	}
}
実行結果
コード2 実行結果

コード2はオイラー角から Quaternion 構造体の値を生成し、その後 eulerAngles プロパティを通して各軸の角度を取得して出力しています。