オブジェクトを駒のように自転させたい場合はどうすればいいの?
クォータニオンを使えば簡単にできるわ!
オブジェクトを指定した軸周りで回転させるには、クォータニオンを使うと簡単です。
次のように1行で回転処理を記述できます。
transform.rotation = Quaternion.AngleAxis(angle, axis) * transform.rotation;
本記事では、オブジェクトを指定した軸と角速度で回転させる方法について、サンプルコードを示しつつ解説していきます。
- Unity2021.1.12f1
指定した軸と角度の回転
Quaternion.AngleAxis()メソッドからクォータニオンとして回転を取得できます。
メソッドの形式は次の通りです。
public static Quaternion AngleAxis(float angle, Vector3 axis);
第1引数angleには、回転させる角度を度数法で指定します。
第2引数axisには、回転軸を指定します。
戻り値は、回転を表すクォータニオンになります。
指定した角速度での回転
オブジェクトを指定した角速度で回転させるには、1フレームの回転角度を次式で求め、先述のQuaternion.AngleAxis()メソッドで毎フレーム回転させます。
1フレームの経過時間はTime.deltaTimeプロパティから取得できます。
したがって、次のような処理を毎フレーム実行すると、指定した角速度での回転を実現できます。
// 1フレームで回転する角度を角速度と経過時間から計算
var angle = angleSpeed * Time.deltaTime;
// 既存のrotationに軸回転のクォータニオンを掛ける
// クォータニオンを掛ける順序に注意
transform.rotation = Quaternion.AngleAxis(angle, axis) * transform.rotation;
クォータニオンの回転は右から適用されていくため、Quaternion.AngleAxis()メソッドを既存の姿勢(transform.rotation)に左から掛けています。
回転の中心位置
オブジェクトが自転する際の中心点はローカル座標の原点となります。
Transform.rotationは、オブジェクトの中心点を基準にした回転になります。
ワールド空間の軸で回転させる
指定した軸と角速度でオブジェクトを回転させるサンプルスクリプトです。
サンプルスクリプト
using UnityEngine;
/// <summary>
/// 指定した軸周りで自転する
/// </summary>
public class AxisRotator : MonoBehaviour
{
// 角速度
[SerializeField] private float _angleSpeed = 90;
// 回転軸
[SerializeField] private Vector3 _axis = Vector3.forward;
private Transform _transform;
// 初期化
private void Awake()
{
// transformに毎回アクセスすると重いので、キャッシュしておく
_transform = transform;
}
// 回転処理
private void Update()
{
// 1フレームで回転する角度を角速度から計算
var angle = _angleSpeed * Time.deltaTime;
// 既存のrotationに軸回転のクォータニオンを掛ける
// クォータニオンを掛ける順序に注意
_transform.rotation = Quaternion.AngleAxis(angle, _axis) * _transform.rotation;
}
}
上記スクリプトをAxisRotator.csとして保存し、回転させたいゲームオブジェクトにアタッチします。
アタッチしたら、インスペクターからパラメータを設定します。
実行結果
指定した軸で自転できるようになりました。
例えば、車の車輪やヘリコプターのプロペラのように、親オブジェクトに合わせて回転軸を変えたい場合はどうするの?
ローカル空間の回転軸で回転させれば可能だわ!
ローカル空間の軸で回転させる
これまで解説した回転では、ワールド空間の回転軸を指定していました。
ローカル空間の軸で回転させるには、transform.rotationの部分をtransform.localRotationに置き換えれば可能です。
サンプルスクリプト
ローカル空間の回転軸と角速度でオブジェクトを回転させる例です。
using UnityEngine;
/// <summary>
/// 指定したローカル空間の軸周りで自転する
/// </summary>
public class LocalAxisRotator : MonoBehaviour
{
// 角速度
[SerializeField] private float _angleSpeed = 90;
// 回転軸
[SerializeField] private Vector3 _axis = Vector3.forward;
private Transform _transform;
// 初期化
private void Awake()
{
// transformに毎回アクセスすると重いので、キャッシュしておく
_transform = transform;
}
// 回転処理
private void Update()
{
// 1フレームで回転する角度を角速度から計算
var angle = _angleSpeed * Time.deltaTime;
// 既存のlocalRotationに軸回転のクォータニオンを掛ける
// クォータニオンを掛ける順序に注意
_transform.localRotation = Quaternion.AngleAxis(angle, _axis) * _transform.localRotation;
}
}
実行結果
親オブジェクトの向きに合わせて回転軸も変化するようになりました。
さいごに
本記事では、指定した軸と角速度でオブジェクトを回転させる方法について解説しました。
このような回転はクォータニオンQuaternion.AngleAxis()を掛けることで実現できます。
紹介した以外の方法に、オイラー角指定で回転させる方法がありますが、ジンバルロックを起こしてしまう可能性があるため、クォータニオンによる回転が安全です。
この方法を応用して、指定した位置を中心に回転させたり、円運動させるような動きも実現できます。詳細は以下記事をご覧ください。