本日は Unity の小ネタ枠です。
Vector3.sqrMagnitudeを使ってより高速な距離比較を行う検証を行います。
Vector3.sqrMagnitude
2点間のベクトルの 2 乗の長さを返します。
Vector3.Distance で2点間の距離を算出する場合、ルートの計算に時間がかかります。
このため、単純に距離の遠近を比較したい場合は sqrMagnitude を利用し、2乗値で比較するようにすると処理が高速に行えます。
docs.unity3d.com
検証シーンの作成
実際にサンプルシーンを作成して2つのコードの実行時間を比較してみます。
指定する2つのオブジェクトとメインカメラの距離を比較して近い方を検出する以下のスクリプトを作成しました。
・DistanceComparison.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class DistanceComparison : MonoBehaviour { [SerializeField, Tooltip("チェック対象A")] private Transform p_ObjectA; [SerializeField, Tooltip("チェック対象B")] private Transform p_ObjectB; // Start is called before the first frame update void Start() { Vector3DistanceCheck(p_ObjectA, p_ObjectB); Vector3SqrMagnitudeCheck(p_ObjectA, p_ObjectB); } void Vector3DistanceCheck(Transform a_ObjectA, Transform a_ObjectB) { // カメラ位置を取得 Transform myPosition = Camera.main.transform; // Stopwatchの開始 System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch(); stopwatch.Start(); // Vector3Distance で距離を取得 float distanceA = Vector3.Distance(myPosition.position, a_ObjectA.position); // Vector3Distance で距離を取得 float distanceB = Vector3.Distance(myPosition.position, a_ObjectB.position); // 経過時間 Debug.Log("ElapsedMilliseconds : " + stopwatch.ElapsedMilliseconds + " ms"); stopwatch.Stop(); // 結果を表示 Debug.Log("distanceA : " + distanceA + ", distanceB : " + distanceB + "."); Debug.Log("Near : " + ((distanceA < distanceB) ? "ObjectA" : "ObjectB") + "."); } void Vector3SqrMagnitudeCheck(Transform a_ObjectA, Transform a_ObjectB) { // カメラ位置を取得 Transform myPosition = Camera.main.transform; // Stopwatchの開始 System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch(); stopwatch.Start(); // Vector3Magnitude で距離の2乗値を取得 float distanceA = Vector3.SqrMagnitude(myPosition.position - a_ObjectA.position); // Vector3Magnitude で距離の2乗値を取得 float distanceB = Vector3.SqrMagnitude(myPosition.position - a_ObjectB.position); // 経過時間 Debug.Log("ElapsedMilliseconds : " + stopwatch.ElapsedMilliseconds + " ms"); stopwatch.Stop(); // 結果を表示 Debug.Log("distanceA : " + distanceA + ", distanceB : " + distanceB + "."); Debug.Log("Near : " + ((distanceA < distanceB) ? "ObjectA" : "ObjectB") + "."); } }
処理時間の計測には以下の記事の方法を利用しています。
bluebirdofoz.hatenablog.com
シーンにスクリプトを配置し、比較する2つのオブジェクトを指定しました。
処理時間の検証
処理を実行してそれぞれの経過時間を表示してみました。
結果としてはどちらもミリ秒未満の処理速度で実行され、1度比較する程度では優位な差は見られませんでした。
普段はあまり意識する必要はないかもしれませんが、ルートの算術演算が通常の算術より時間がかかるのは確かなため、非常に多くの距離計算を毎フレーム行う場合などは試してみるとよいかもしれません。