3D アプリケーションの回転は、たいていクォータ二オンかオイラー角のどちらかによって表されています。それぞれ、利点と欠点があります。Unity では内部でクォータ二オンを採用していますが、編集しやすいように、Inspector では同等のオイラー角で表しています。
Euler angles are represented by three angle values for X, Y and Z that are applied sequentially. To apply a Euler rotation to a particular GameObject, each rotation value is applied in turn, as a rotation around its corresponding axis.
クォータニオンは、オブジェクトの向きや回転を表すのに使用されます。この表現法では、内部で 4 つの数字 (Unity では x、y、z、w と呼びます) で構成されています。ただし、この数字は、角度や軸を表現しているわけでなく、通常、直接アクセスすることはありません。クォータ二オン (四元数) について特別に興味がない限り、クォータニオンが 3D 空間の回転を表しているのだということを知っているだけで十分で、通常、x、y、z プロパティを操作したり変更することはありません。
ベクトルが位置と方向 (方向は原点から測ります) を表現するのと同様に、クォータ二オンは向きと回転を表現できます。回転は、回転「基準」か「単位」を基準に測られます。回転を、ある向きからもう一方の向きへの方向として計測するため、クォータ二オンでは、180 度より大きな回転を表現することができません。
Unity では、ゲームオブジェクトのすべての回転は、内部ではクォータ二オンで保存します。なぜなら、利点のほうが、制限を上回るためです。
Transform Inspector では、オイラー角を使って rotation (回転) を表示します。なぜなら、この方が理解しやすく、編集しやすいからです。Unityは、ゲームオブジェクトの回転のために Inspector に入力された新しい値を、ゲームオブジェクトの新しいクォータ二オンの回転値に変換します。
この影響で、Inspector に X: 0, Y: 365, Z: 0 ゲームオブジェクトの回転値の入力が可能になります。このような値はクォータニオンでは表せないため、再生モードで、ゲームオブジェクトの回転値は X: 0, Y: 5, Z: 0 に変わります。これは「360度のフル回転プラス 5 度」という概念のないクォータニオンに回転値が変換されたため、値は、回転が同じ方向になるように、単純に置き換えられたものです。
スクリプトで回転を扱うとき、Quaternion クラスとその関数を使用し、回転値を作成、変更します。ある状況では、オイラー角の使用が有効な場合もあります。ただし、以下を注意する必要があります。 - オイラー角を扱える Quaternion クラス関数を使用してください。 - 回転からオイラー角を取得、変更、再適用することは、意図しない作用の原因になることがあります。
Unity の Quaternion クラスには、多くの関数が備わっており、オイラー角をまったく使用しないで回転を作成し、操作することができます。以下は、その例です。
作成
操作
However sometimes it’s desirable to use Euler angles in your scripts. In this case it’s important to note that you must keep your angles in variables, and only use them to apply them as Euler angles to your rotation. While it’s possible to retrieve Euler angles from a quaternion, if you retrieve, modify and re-apply, problems are likely to arise.
ここで、一般的によくある 誤り を、ゲームオブジェクトを X 軸の周りで 1 秒につき 10 度回転させようろする例を使用して紹介します。以下は 行うべきでない 事例です。
// rotation scripting mistake #1
// the mistake here is that we are modifying the x value of a quaternion
// this value does not represent an angle, and does not produce desired results
void Update ()
{
var rot = transform.rotation;
rot.x += Time.deltaTime * 10;
transform.rotation = rot;
}
// rotation scripting mistake #2
// Read, modify, then write the Euler values from a Quaternion.
// Because these values are calculated from a Quaternion,
// each new rotation might return very different Euler angles, which might suffer from gimbal lock.
void Update ()
{
var angles = transform.rotation.eulerAngles;
angles.x += Time.deltaTime * 10;
transform.rotation = Quaternion.Euler(angles);
}
以下は、スクリプトでオイラー角を使う時の 正しい 使用法です。
// Rotation scripting with Euler angles correctly.
// Store the Euler angle in a class variable, and only use it to
// apply it as a Euler angle, but never rely on reading the Euler back.
float x;
void Update ()
{
x += Time.deltaTime * 10;
transform.rotation = Quaternion.Euler(x,0,0);
}
See documentation on Quaternion.Euler for more details.
Unity 内部の Animation ウィンドウ を含め、多くの 3D オーサリングパッケージでは、アニメーションの間に、オイラー角で回転を指定することができます。
このような回転値は、しばしば、クォータニオンで表現できる範囲を超越することがあります。例えば、ゲームオブジェクトがその場で 720 度回転する場合、オイラー角では X: 0, Y: 720, Z:0 と示します。しかし、これは、実際にクォータニオンで表現できる値ではありません。
Unity のアニメーションウィンドウ内で、どのように回転を補間するか ( クォータニオンとオイラー角どちらを使用するか ) を指定できるオプションがあります。オイラー角での補間を指定すると、Unity は角度で指定されたすべての範囲を含む動きを可能にします。一方、クォータニオン回転では、単に特定の向きを向かせることが目的なので、Unity は、クォータニオン補間で最短距離を通って回転させます。詳しい情報は、アニメーションカーブを使用するを参照してください。
アニメーションを外部ソースからインポートする場合、これらのファイルは、通常はオイラー形式の回転キーフレームアニメーションを含んでいます。Unity のデフォルトのビヘイビアでは、これらのアニメーションをリサンプルして、各フレームごとに新しくクォータニオンキーフレームを生成し、キーフレーム間の回転がクォータニオンの有効範囲を超える状況をすべて回避しようとします。
例えば、6 フレーム離れた 2 つのキーフレーム (最初のフレームの X 値が 0、 2 番目のフレームの X 値が 270) があるとします。リサンプリングしないと、クォータニオン補間では、この 2 つのキーフレームを 90 度逆方向に回転させます。なぜなら、これが、最初の向きから2番目の向きにするための最短の方法だからです。しかし、リサンプリングして各フレームにキーフレームを加えると、今度はキーフレーム間では 45 度しかないので、正しく回転します。
リサンプリングを行っても、インポートしたアニメーションのクォータニオン表示がオリジナルに十分近い値にならない場合があります。このため、Unity 5.3 以降では、アニメーションリサンプリングをオフにするオプションがあります。これを使うと、代わりに、ランタイムにオイラーアニメーションキーフレームを使用します。詳しい情報は、Animation Import of Euler Curve Rotations を参照してください。