↪️
【Unity】ジンバルロックの理解と回避方法
この記事では、ジンバルロックの仕組みや影響について解説しています。
ジンバルロックとは?
ジンバルロックは、オイラー角で回転を管理する際に、座標系の2つの回転軸が同一平面上に重なり、回転の自由度が1つ失われる現象です。これは、オイラー角の回転順序が原因で発生します。
- Unityでは、X → Y → Zの順番で回転します
- X軸を90°回転させた場合、Y軸とZ軸が同一平面に配置されます。
- この結果、Y軸とZ軸回転が同じ方向に作用し、意図した回転ができなくなります。
ジンバルロックの仕組み
-
オイラー角の回転順序
Unityでは、オイラー角を使った回転では「X → Y → Z」の順で回転が適用されます。累積した回転の影響で、各軸の方向が変わり、ジンバルロックとして現れます。
-
X軸を90°回転するとどうなるか?
- Y軸がZ軸に一致。
- Z軸がY軸に一致。
- この結果、Y軸とZ軸が同一平面上に重なり、互いに区別がつかなくなるため、回転の自由度が1つ失われます。これがジンバルロックの状態です。
サンプルコード:ジンバルロックの検証
以下のコードを使用すると、ジンバルロックの問題を視覚的に確認できます。
public class GimbalLockTester : MonoBehaviour
{
[SerializeField] private Transform _target;
[SerializeField] private float _rotationSpeed = 50f;
private Vector3 _currentEulerAngles;
private void Start()
{
if (_target != null)
{
_currentEulerAngles = _target.eulerAngles;
}
}
private void Update()
{
if (_target == null) return;
//初期化
if (Input.GetKey(KeyCode.Space))
{
_currentEulerAngles = new Vector3(0, 0, 0);
}
// X軸回転(上下)
if (Input.GetKey(KeyCode.UpArrow))
{
_currentEulerAngles.x += _rotationSpeed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.DownArrow))
{
_currentEulerAngles.x -= _rotationSpeed * Time.deltaTime;
}
// Y軸回転(左右)
if (Input.GetKey(KeyCode.LeftArrow))
{
_currentEulerAngles.y += _rotationSpeed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.RightArrow))
{
_currentEulerAngles.y -= _rotationSpeed * Time.deltaTime;
}
// Z軸回転(前後)
if (Input.GetKey(KeyCode.Z))
{
_currentEulerAngles.z += _rotationSpeed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.X))
{
_currentEulerAngles.z -= _rotationSpeed * Time.deltaTime;
}
// 回転を適用
_target.eulerAngles = _currentEulerAngles;
// デバッグ情報
Debug.Log($"Euler Angles: {_currentEulerAngles}");
}
}
動作手順
- 上記スクリプトをアタッチし、
_target
にそのオブジェクトを設定。 - 以下のキーを押して回転操作を試します:
- 矢印キー上/下: X軸回転
- 矢印キー左/右: Y軸回転
- Z/X: Z軸回転
結果
- X軸を90°回転後、Y軸を回転しようとすると、ローカルZ軸が一緒に回転し、操作が意図しない方向に影響を及ぼします。
- これがジンバルロックの現象です。
まとめ
ジンバルロックは、オイラー角の特性によって発生する問題で、3D回転の管理が意図通りに動作しなくなる現象です。Quaternionを使用することで、この問題を回避し、スムーズな回転処理を実現できます。
- ジンバルロックの発生状況: ローカルY軸とZ軸が同一平面上に重なると発生。
- 回避策: Quaternionを使い、累積的な回転計算を行う。
参考サイト
Discussion