// X軸で90度回転
var rot1 = Quaternion.AngleAxis(90, new Vector3(1, 0, 0));
// Y軸で90度回転
var rot2 = Quaternion.AngleAxis(90, new Vector3(0, 1, 0));
// Quaternionの回転、左が先か?右が先か?
var rot = rot1 * rot2;
左が先説
Quaternionの掛け算についてUnity公式には以下の記述があります。
lhs と rhs の回転を組合わせます。
lhs * rhs の積の値で回転させることは、lhs を最初に、それから rhs というように 2 つの回転を順番に行うことと同じです。つまり、回転は、非可換性で、lhs * rhs は rhs * lhs と異なる回転を表すということに気を付けてください。
https://docs.unity3d.com/ja/2019.4/ScriptReference/Quaternion-operator_multiply.html より
// https://docs.unity3d.com/ja/2019.4/ScriptReference/Quaternion-operator_multiply.html より
using UnityEngine;
using System.Collections;
public class Example2 : MonoBehaviour
{
float rotateSpeed = 90;
// Applies a rotation of 90 degrees per second around the Y axis
void Update()
{
float angle = rotateSpeed * Time.deltaTime;
transform.rotation *= Quaternion.AngleAxis(angle, Vector3.up);
}
}
ここには計算順は 左が先、右が後 ということ、回転は非可換で逆にはできないということが記載されています。
しかし計算順は本当に 左が先、右が後 なのでしょうか。
右が先説
以下のようにX軸で90度回転してからY軸で90度回転させるにはどうしたらいいでしょうか。
これを実現するためのコードを書くとこのようになります。
(アニメーションはしません)
// X軸で90度回転
var rot1 = Quaternion.AngleAxis(90, new Vector3(1, 0, 0));
// Y軸で90度回転
var rot2 = Quaternion.AngleAxis(90, new Vector3(0, 1, 0));
// X軸で90度回転してからY軸で90度回転
transform.localRotation = rot2 * rot1;
これを見ると右(X軸で90度回転)が先で左(Y軸で90度回転)が後のようです。
どちらが正しいか
どちらも正しい と言えます。
左が先説と右が先説では考え方が違います。
左が先説の場合は回転で 回転軸も同時に回転する と考えます。
前述の例で説明します。
// X軸で90度回転
var rot1 = Quaternion.AngleAxis(90, new Vector3(1, 0, 0));
// Y軸で90度回転
var rot2 = Quaternion.AngleAxis(90, new Vector3(0, 1, 0));
transform.localRotation = rot2 * rot1;
左から回転すると考える場合、まずオブジェクトをY軸で90度回転します。
この時、回転軸も回転するのでX軸が-Z軸になります。
そしてこの回転後のX軸を基準に90度回転します。
右から左の場合は 回転軸は変わらず常に固定 と考えます。
どちらから回転を掛ければいいのか
オブジェクトを回転させたい場合、どちらから回転を掛ければいいでしょうか。
答えは 何を実現したいか によって変わります。
既に回転されたオブジェクトを 元々の回転軸で回転させたい 場合はオブジェクトの回転を左、掛けたい回転を右にしましょう。
void Start()
{
// Z軸で30度回転しておく
transform.localRotation = Quaternion.AngleAxis(30, new Vector3(0, 0, 1));
}
void Update()
{
var rotateSpeed = 90;
var angle = rotateSpeed * Time.deltaTime;
// 元々のY軸で回転
var rot = Quaternion.AngleAxis(angle, Vector3.up);
transform.localRotation = transform.localRotation * rot;
}
既に回転されたオブジェクトを 固定の回転軸で回転させたい 場合は掛けたい回転を左、オブジェクトの回転を右にしましょう。
void Start()
{
// Z軸で30度回転しておく
transform.localRotation = Quaternion.AngleAxis(30, new Vector3(0, 0, 1));
}
void Update()
{
var rotateSpeed = 90;
var angle = rotateSpeed * Time.deltaTime;
// 固定のY軸で90度回転
var rot = Quaternion.AngleAxis(angle, Vector3.up);
transform.localRotation = rot * transform.localRotation;
}
まとめ
どちらが先か、という問題については考え方次第で どちらにも解釈できる ということが分かりました。
ただしQuaternionによる回転が 任意の軸の周りでの回転 を表現していることを考えると右から左の方が自然に見えます。
var pos = new Vector3(0, 0, 1);
var xRot = Quaternion.AngleAxis(90, new Vector3(1, 0, 0));
var yRot = Quaternion.AngleAxis(90, new Vector3(0, 1, 0));
// X軸で90度回転する
var pos2 = xRot * pos;
// Y軸で90度回転する
var pos3 = yRot * pos2;
// X軸で90度回転させてからY軸で90度回転する
// 右から左の順
var pos4 = yRot * xRot * pos;
// pos3とpos4は等しい
参考
Quaternionによる3次元の回転変換
クォータニオン (Quaternion) を総整理! ~ 三次元物体の回転と姿勢を鮮やかに扱う ~
Quaternion を完全に理解した | VirtualCast Blog