MRが楽しい

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

オブジェクトの座標を指定の面に投影する

本日は Unity の小ネタ枠です。
オブジェクトの座標を指定の面に投影する方法を記事にします。
f:id:bluebirdofoz:20210911004430j:plain

2022/1/31追記

本記事の方法では平面の位置を移動した場合、正確に座標を投影できない問題がありました。
以下の記事で平面を動かした場合でも追従可能な方法を記事にしているので、こちらを参照ください。
bluebirdofoz.hatenablog.com

Vecotr3.ProjectOnPlane

Vecotr3.ProjectOnPlane は垂直な法線ベクトルによって定義される平面上にベクトルを射影します。
docs.unity3d.com

サンプルシーンの作成

シーンを作成して試してみます。
ベクトルを投影する平面オブジェクトを作成します。
f:id:bluebirdofoz:20210911004445j:plain

Vecotr3.ProjectOnPlane を利用するには平面の法線ベクトルを取得する必要があります。
スクリプトでは forward 方向を法線方向として扱いたかったので、オブジェクトを2重構造にしてオブジェクトの回転方向を調整しました。
f:id:bluebirdofoz:20210911004457j:plain

次に投影を行う Sphere オブジェクトを追加します。
f:id:bluebirdofoz:20210911004506j:plain

最後に投影箇所を示す Sphere オブジェクトを作成してシーンの準備ができました。
f:id:bluebirdofoz:20210911004516j:plain

サンプルスクリプト

Vecotr3.ProjectOnPlane を使って投影位置を計算するサンプルスクリプトを作成しました。
投影元となるオブジェクトと平面オブジェクトを指定しておくと、スクリプトをアタッチしたオブジェクトを平面への投影位置に移動します。
・TrackingProjectOnPlane.cs

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

public class TrackingProjectOnPlane : MonoBehaviour
{
    [SerializeField, Tooltip("追跡対象オブジェクト")]
    private Transform p_TrackingTransform;

    [SerializeField, Tooltip("投影する平面(平面の法線方向とforwardが一致する事)")]
    private Transform p_ProjectPlane;

    void Update()
    {
        if(p_TrackingTransform != null && p_ProjectPlane != null)
        {
            // 追跡対象オブジェクトを平面に投影した位置にオブジェクトを移動する
            this.transform.position = Vector3.ProjectOnPlane(p_TrackingTransform.position, p_ProjectPlane.forward);
        }
    }
}

f:id:bluebirdofoz:20210911004525j:plain

作成したスクリプトを投影箇所を示す Sphere オブジェクトに設定し、投影元のオブジェクトと平面オブジェクトを指定しました。
f:id:bluebirdofoz:20210911004534j:plain

動作確認

シーンを再生して動作を確認します。
f:id:bluebirdofoz:20210911004544j:plain

投影元のオブジェクトを移動すると、投影箇所を示すオブジェクトが平面に沿って動きます。
f:id:bluebirdofoz:20210911004554j:plain

試しに平面を傾けてみます。
f:id:bluebirdofoz:20210911004604j:plain

平面を傾けた場合も、その法線に沿って追跡されたオブジェクトが投影されていることが分かります。
f:id:bluebirdofoz:20210911004612j:plain