MRが楽しい

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

Unityでオブジェクトの正面側と背面側のどちらにカメラが存在するか判定する

本日はUnityの小ネタ枠です。
Unityでオブジェクトの正面側と背面側のどちらにカメラが存在するか判定する方法です。

Transform.forward

Transform.forwardはオブジェクトの正面方向(シーンビュー上の青い矢印方向)の正規化されたベクトルを返します。
docs.unity3d.com

Vector3.Dot

Vector3.Dotは2つのベクトルの内積を算出します。
オブジェクトの正面方向とオブジェクトから見たカメラ方向の内積からカメラの位置が正面方向か背面方向かを判定できます。
docs.unity3d.com

Transform cameraTransform = Camera.main.transform; // カメラ座標を取得
Vector3 toCamera = (transform.position - cameraTransform.position).normalized;
float dot = Vector3.Dot(transform.forward, toCamera); // オブジェクトの正面方向とカメラ方向の内積を取得

// 計算結果が0以上なら正面を向いている、0未満なら背面を向いている
float threshold = 0.0f;
bool result = (dot >= threshold);

敷居値を変更することで正面と背面だけでなくどの程度の正面角に含まれるかも判定可能です。
・threshold = 1.0f:完全な正面方向
・threshold = 0.9f:18度以内
・threshold = 0.7f:45度以内

サンプルスクリプト

オブジェクトが正面を向いているときのみオブジェクトを有効にする以下のサンプルスクリプトを作成しました。
・ObjectFrontChecker.cs

using UnityEngine;

public class ObjectFrontChecker : MonoBehaviour
{
    [SerializeField]
    private bool isFacingFront = false;
    
    void Update()
    {
        if (Camera.main == null) return;
        // カメラからオブジェクトへの方向を計算
        Vector3 toCamera = (transform.position - Camera.main.transform.position).normalized;
        // オブジェクトの正面方向とカメラが存在する方向を内積計算
        float dot = Vector3.Dot(transform.forward, toCamera);
        
        // 計算結果が0以上なら正面を向いている、0未満なら背面を向いている
        var checkResult = dot >= 0.0f;
        
        if (isFacingFront != checkResult)
        {
            isFacingFront = checkResult;
            Debug.Log(isFacingFront ? "正面" : "背面");

            // 正面を向いている場合のみ子オブジェクトをアクティブにする
            foreach (Transform child in transform)
            {
                child.gameObject.SetActive(isFacingFront);
            }
        }
    }
}

以下の通りオブジェクトの正面側にカメラが存在するときはオブジェクトが有効になり、背面側にカメラが回り込むと無効になりました。