MRが楽しい

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

オブジェクトの座標を指定の面に投影する(指定の座標に対して平面上の最も近い点を取得する)

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

Plane.ClosestPointOnPlane

Plane.ClosestPointOnPlane は指定の座標に対して、平面上の最も近い点を返します。
これは座標を面に投影した位置ということになります。
docs.unity3d.com

サンプルシーンの作成

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

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

サンプルスクリプト

Plane.ClosestPointOnPlane を使って投影位置を計算するサンプルスクリプトを作成しました。
投影元となるオブジェクトと平面オブジェクトを指定しておくと、スクリプトを設定したオブジェクトが常に平面への投影位置に追従します。
・TrackingClosestPointOnPlane.cs

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

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

    [SerializeField, Tooltip("投影する平面")]
    private Transform p_ProjectPlane;

    void Update()
    {
        if(p_TrackingTransform != null && p_ProjectPlane != null)
        {
            // 投影する平面を取得する
            Plane projectionPlane = new Plane(p_ProjectPlane.up, p_ProjectPlane.position);

            // 平面と追跡対象が最も近い座標を求める(投影位置)
            Vector3 projectionPosition = projectionPlane.ClosestPointOnPlane(p_TrackingTransform.position);

            // 追跡対象オブジェクトを平面に投影した位置に自身を移動する
            this.transform.position = projectionPosition;
        }
    }
}

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

動作確認

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

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

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