MRが楽しい

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

Unityでゲームオブジェクトがカメラの方向を常に向き続けるコンポーネントを作成する

本日は Unity の小ネタ枠です。
Unityでゲームオブジェクトがカメラの方向を常に向き続けるコンポーネントを作成してみます。

カメラ方向へのベクトルを取得する

ゲームオブジェクトをカメラ方向に向けるには、カメラ方向へのベクトルを回転に変換してゲームオブジェクトの回転に反映します。
カメラ方向へのベクトルは現在のゲームオブジェクトの座標からカメラオブジェクトを座標を減算することで計算できます。

// 現オブジェクトからメインカメラ方向のベクトルを取得する
Vector3 direction = CameraCache.Main.transform.position - this.transform.position;

// オブジェクトをベクトル方向に従って回転させる
transform.rotation = Quaternion.LookRotation(direction);

UI をカメラ方向に向けたい場合は、UI は Z 軸の負方向が正面になるため、回転を反転する必要がある点に注意が必要です。

// オブジェクトをベクトル方向に従って回転させる
// (正面方向を反転させる場合)
transform.rotation = Quaternion.LookRotation(-1.0f * direction);

更に X または Y の軸方向の変量を 0 にすることで回転軸を固定することもできます。
今回カメラの傾きは考慮していないので Z 軸方向の回転は自動で固定されています。

// ベクトルの固定軸を考慮する
Vector3 lockDirection = lockAxis switch
{
    // ロック軸なしの場合はベクトルをそのまま利用する
    LockAxis.None => direction,
    // X軸固定の場合はX軸方向のベクトルの変量を0にする
    LockAxis.X => new Vector3(0.0f, direction.y, direction.z),
    // Y軸固定の場合はY軸方向のベクトルの変量を0にする
    LockAxis.Y => new Vector3(direction.x, 0.0f, direction.z),
    _ => throw new ArgumentOutOfRangeException()
};

サンプルスクリプト

上記の機能を組み合わせてサンプルスクリプトを作成しました。
コンポーネントをアタッチしたゲームオブジェクトは常にカメラ方向を向くようになります。
Inspector から固定する回転軸の指定や正面方向の反転(UI利用時など)が設定できます。

・CameraBillboard.cs

using System;
using Microsoft.MixedReality.Toolkit.Utilities;
using UnityEngine;

public class CameraBillboard : MonoBehaviour
{
    /// <summary>
    /// 固定軸の定義
    /// </summary>
    private enum LockAxis
    {
        None,
        X,
        Y,
    }

    /// <summary>
    /// 固定する回転軸の指定
    /// </summary>
    [SerializeField] private LockAxis lockAxis;

    /// <summary>
    /// 正面方向を逆転するか否か
    /// (UIの場合はZ軸の負方向が正面になるので true を利用する)
    /// </summary>
    [SerializeField] private bool reverseFront;

    private void Update()
    {
        // 現オブジェクトからメインカメラ方向のベクトルを取得する
        Vector3 direction = CameraCache.Main.transform.position - this.transform.position;

        // ベクトルの固定軸を考慮する
        Vector3 lockDirection = lockAxis switch
        {
            // ロック軸なしの場合はベクトルをそのまま利用する
            LockAxis.None => direction,
            // X軸固定の場合はX軸方向のベクトルの変量を0にする
            LockAxis.X => new Vector3(0.0f, direction.y, direction.z),
            // Y軸固定の場合はY軸方向のベクトルの変量を0にする
            LockAxis.Y => new Vector3(direction.x, 0.0f, direction.z),
            _ => throw new ArgumentOutOfRangeException()
        };
        
        // オブジェクトをベクトル方向に従って回転させる
        // (正面方向を逆転する場合はベクトルにマイナスをかける)
        transform.rotation = Quaternion.LookRotation(reverseFront ? -lockDirection : lockDirection);
    }
}