こんにちは、ともくんのゲーム作り部屋にようこそ!
このページでは、
「Quaternionってなに?」
「Quaternionでどうやって回転させるの?」
というお悩みの方に向けた内容となっています。
Unityでは、主に3次元におけるオブジェクトの回転や向きを表現する際に、Quaternion(クォータニオン)という構造体を使って表します。
このQuaternionとは、四元数とも呼ばれますが、4つの数値を用いてオブジェクトの回転を計算して表している手法のことです。
オブジェクトの回転は、TransformコンポーネントのRotationの項目で、3つの軸における角度を確認できますが、Unityの内部では、これらも全てQuaternion型で保持されています。
そこでこのページでは、Unityでオブジェクトの回転を表すQuaternion(クォータニオン)という構造体について、どういうものなのか、またQuaternionの基本的な使い方についてまとめていきます。
Quaternion(クォータニオン)とは?
まずは、Unityで使われているQuaternionがどういうものなのか、について紹介していきます。
3Dオブジェクトの向きや回転を表している構造体
Quaternionは、冒頭でも解説した通り、Unityのオブジェクトの向きや回転を表している構造体となっています。
このQuaternionは、x・y・z・wという4つの数字(四元数)で構成されていて、この数字を使ってオブジェクトの回転を計算して表現しています。
ただし、この4つの数字は、直接角度などを指定しているものではなく、あくまでも回転や向きを決める際に使われている値となっています。
例えば、何かを回転させようとした場合、通常では「30度」などという角度を設定しますが、Quaternionでは直接角度を指定するわけではなく、x・y・z・wの値を使ってオブジェクトを30度回転させる、ということになります。
このようにQuaternionは、直接角度を指定するものではないため、少し理解しにくい部分がありますが、あくまでもUnityのオブジェクトの向きや回転はQuaternionという型で保持していると考えておきましょう。
Quaternionはジンバルロックの影響を受けない
少し理解しにくいQuaternionを使う理由として、ジンバルロックという回転の自由度が失われてしまう欠点を回避することができるからです。
3Dオブジェクトを回転する際に、Quaternionではなく、Euler(オイラー角)を使って表す方法もあります。
このEulerは、X軸・Y軸・Z軸に回転させたい角度を直接指定することで、オブジェクトを直感的に回転させることができる方法です。

非常に理解しやすい方法ですが、一つ欠点があり、回転により2つの軸が重なり合ってしまうことで、一つの軸が消えてしまい回転できなくなってしまう、ジンバルロックという現象が起きてしまいます。
このジンバルロックという現象を防ぐために、UnityではQuaternionが使われています。
TransformのrotationもQuaternion型で保持されている
Unityでは、オブジェクトの向きをTransformコンポーネントのrotationという変数が管理していて、インスペクターウィンドウから確認することができます。

このインスペクターウィンドウでのrotationの項目は、X軸・Y軸・Z軸において回転させる角度を直接指定することができる、つまりEuler(オイラー角)を設定できる項目です。
一見、先ほどのQuaternionの説明と矛盾しているように感じますが、実は、このrotationの値は、内部ではQuaternion型で保持されていて、インスペクターウィンドウ上ではあくまでもこのQuaternionから計算されたEulerが表示されていることになります。
例えば、以下のようにインスペクターウィンドウのrotationに、直接角度を入れてオブジェクトを回転させてみます。

そして、スクリプトからDebug.Logを使って、rotationの値をコンソールウィンドウに表示させてみます。
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
Debug.Log(transform.rotation); // transform.rotationの値を表示する
}
}

インスペクターウィンドウに設定した値とは全く異なる数字で、かつ4つの数字が表示されています。
これより、rotationの値を内部ではQuaternion型で管理されているというのが分かると思います。
Quaternion(クォータニオン)の基本的な使い方
ここからは、Quaternionの基本的な使い方を紹介していきます。
実際に以下のオブジェクトを使って、Quaternionで回転させるという簡単な処理を作ってみます。

オブジェクトの回転の向きをQuaternion型で取得する
まずは、スクリプトからオブジェクトの向きをQuaternion型で取得していきます。
using UnityEngine;
public class Test : MonoBehaviour
{
void Update()
{
Quaternion objQuaternion = transform.rotation; // オブジェクトのQuaternionを取得する
}
}
他のクラスや構造体と同じく、7行目でQuaternion型の変数を宣言してtransform.rotationの値を代入しておきます。
ここでは、Updateメソッド内で代入しているので、フレーム毎にオブジェクトの回転の向きを取得していくことになります。
回転させたい動きをQuaternion型で作成する
次に、オブジェクトに対して回転させたい動きをQuaternion型で作成していきます。
ただ、前述の説明の通り、Quaternionは直接角度などの値を指定することができません。
そこで、Quaternionの中で定義されているメソッドを使って、回転させる動きを作っていきます。
ここでは、よく使われるEulerメソッドを使って回転させる動きを作成していきます。
using UnityEngine;
public class Test : MonoBehaviour
{
void Update()
{
Quaternion objQuaternion = transform.rotation; // オブジェクトのQuaternionを取得する
Quaternion rotationQuaternion = Quaternion.Euler(0.5f, 1.0f, 1.5f); // 回転させるQuaternionを作成する
}
}
8行目でEulerメソッドを使って、回転させるQuaternionを作成しています。
このEulerメソッドは、引数でX軸・Y軸・Z軸における角度を指定することで、その値をQuaternion型に変換・計算してくれるメソッドです。
Quaternion.Euler(X軸の回転角度, Y軸の回転角度, Z軸の回転角度);
これで、回転させたい動きのQuaternion型を作成できました。
2つのQuaternionを乗算して合体させる
元のQuaternionの値に、回転させたいQuaternionの値を合わせることで、回転させることができるようになります。
using UnityEngine;
public class Test : MonoBehaviour
{
void Update()
{
Quaternion objQuaternion = transform.rotation; // オブジェクトのQuaternionを取得する
Quaternion rotationQuaternion = Quaternion.Euler(0.5f, 1.0f, 1.5f); // 回転させるQuaternionを作成する
Quaternion unionQuaternion = objQuaternion * rotationQuaternion; // 2つのQuaternionを合成する
transform.rotation = unionQuaternion; // 合成したQuaternionを回転量にセットする
}
}
9行目で2つのQuaternionの値を乗算して、合成させる処理を作っています。
Quaternion型は加算ではなく乗算することで、2つの値を合成することができ、回転量を更新することができます。
最後に、10行目でオブジェクトのtransform.rotationに、できあがったQuaternionの値を代入してあげることで、

上記のようにオブジェクトを回転させる処理を作ることができます。
まとめ
このページでは、Unityでオブジェクトの回転を管理しているQuaternionという構造体について、どんな構造体なのか、また使い方までをまとめていきましたが、いかがでしたでしょうか?
Quaternionとは、オブジェクトの回転や向きを表している構造体で、内部で4つの数字を使ってオブジェクトの回転を管理しています。
Unityでのオブジェクトの回転はすべてこのQuaternionで管理されていて、transform.rotationも内部ではQuaternion型で値が保持されています。
Quaternionは、少し理解しにくい部分がありますが、Unityでは必ず使用することになるので、少しずつ覚えていきましょう。
最後までお読みいただきまして、ありがとうございました!
コメント