Unity では、Quaternion クラスを使用して、ゲームオブジェクトの 3 次元の向きを保存したり、ある向きから別の向きへの相対的な回転を示したりします。
このページでは、Quaternion クラスの概要と、Quaternion クラスでスクリプトを作成する際の一般的な使い方について説明します。Quaternion クラスのすべてのメンバーを網羅したリファレンスについては、Quaternion のスクリプトリファレンス を参照してください。
オイラー (Euler) 角 (Inspector に表示されるゲームオブジェクトの回転を表す X、Y、Z の値) と、Unity がゲームオブジェクトの実際の回転を保存するために使用する内部的なクォータニオン (Quaternion) 値の違いを理解することは重要です。このトピックの基本については、Unity の回転と向き を参照してください。
スクリプトで回転を扱うとき、Quaternion クラスとその関数を使用し、回転値を作成、変更します。ある状況では、オイラー角の使用が有効な場合もあります。ただし、以下を注意する必要があります。 - オイラー角を扱える Quaternion クラス関数を使用してください。 - 回転からオイラー値を取得、修正、再適用すると、意図しない副作用が発生することがあります (以下参照)。
Unity の Quaternion クラスには、オイラー角を全く使わずに回転を作成、操作できる関数がいくつかあり、ほとんどのケースでこれらを使用するべきです。これらの関数はそれぞれ、コードサンプルのあるスクリプトリファレンスにリンクしています。
Transform クラスには、Quaternion の回転を操作するためのメソッドも用意されています。
場合によっては、スクリプトでオイラー角を使用する方が望ましいこともあります。その場合は、角度を変数に格納し、オイラー角として回転に適用するためだけに使用し、最終的にはクォータニオンとして保存しなければならないことに注意してください。クォータニオンからオイラー角を取得することは可能ですが、取得、修正、再適用を行うと問題が発生する可能性が高くなります。
このような問題がどのように発生するかについての詳細は、eulerAngles のスクリプトリファレンス を参照してください。
ここで、一般的によくある誤りを、ゲームオブジェクトを 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 an 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);
}