MRが楽しい

MRやVRについて学習したことを書き残す

Unity でオブジェクトを水平または垂直に維持する

本日は Unity の小ネタ枠です。
Unity でオブジェクトを水平または垂直に維持する実装を試したので記事にします。

サンプルシーン

サンプルシーンとして MRTK の Billboard コンポーネントを設定した2つのオブジェクトを持つシーンを用意しました。

シーンを再生すると以下の通り、Plane オブジェクトの forward 方向が常にカメラの方を向くように追従します。

この自由に回転する2つのオブジェクトについてそれぞれ水平または水平方向に回転を固定してみます。

実装方法

水平の維持はY軸以外の回転を 0 にすることで可能です。
オブジェクトの up ベクトルが常に Vector3.up(上方向) に一致します。

this.transform.rotation = Quaternion.Euler(0.0f, this.transform.rotation.eulerAngles.y, 0.0f);

垂直の維持ではそこからRotate関数を用いてX軸またはZ軸方向に90度回転させます。
今回のサンプルシーンではX軸方向に-90度回転させてオブジェクトの up ベクトルが常にカメラ方向を向くようにします。

this.transform.rotation = Quaternion.Euler(0.0f, this.transform.rotation.eulerAngles.y, 0.0f);
this.transform.Rotate(-90.0f, 0.0f, 0.0f);

Rotate 関数は relativeTo 引数を指定しない場合、デフォルトでローカル座標の回転軸(Space.Self)に対する回転が行われます。
docs.unity3d.com

サンプルスクリプト

以下のサンプルスクリプトを作成しました。
・AxisLocker.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AxisLocker : MonoBehaviour
{
    [System.Serializable]
    private enum AxisLockType
    {
        Nothing,
        Horizontal,
        Vertical
    }

    [SerializeField, Tooltip("固定向き")]
    private AxisLockType axisLock;

    /// <summary>
    /// 定期実行
    /// </summary>
    void LateUpdate()
    {
        switch (axisLock)
        {
            case AxisLockType.Nothing:
                break;
            case AxisLockType.Horizontal:
                // オブジェクトを水平に維持する
                this.transform.rotation = Quaternion.Euler(0.0f, this.transform.rotation.eulerAngles.y, 0.0f);
                break;
            case AxisLockType.Vertical:
                // オブジェクトを垂直(X軸:-90°)に維持する
                this.transform.rotation = Quaternion.Euler(0.0f, this.transform.rotation.eulerAngles.y, 0.0f);
                this.transform.Rotate(-90.0f, 0.0f, 0.0f);
                break;
        }
    }
}

それぞれ水平に保ちたいオブジェクトには[axisLock:Horizontal]で、垂直に保ちたいオブジェクトには[axisLock:Vertical]で設定します。

シーンを再生して動作を確認します。
以下の通り、オブジェクトが水平または垂直に維持されたままカメラの方を向くようになります。