MRが楽しい

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

MRTK2.5でNavMeshComponentsを使って動的経路探索を試す その1

本日は MRTK と NavMesh の技術調査枠です。
MRTK2.5でNavMeshComponentsを使って動的経路探索を試す手順を記事にします。
f:id:bluebirdofoz:20210207232048j:plain

本記事は SpatialAwareness の動的経路探索です。

NavMeshComponents

NavMeshComponents は NavMesh を活用するための以下の4つのコンポーネントを提供します。
・NavMeshSurface
・NavMeshModifier
・NavMeshModifierVolume
・NavMeshLink
github.com

今回はこの NavMeshComponents を使って MRTK が構成する SpatialAwareness のメッシュに動的に NavMesh を適用します。

NavMeshComponentsの取得

以下のページから NavMeshComponents をダウンロードします。
今回は[DownloadZIP]から直接ダウンロードを行いました。
f:id:bluebirdofoz:20210207232154j:plain

NavMeshComponents を取得する際にはエディターのバージョンに合わせたブランチを利用することが推奨されています。
今回はコードの一部のみの利用のため、master ブランチから取得しても問題ありませんでした。

Please use the branch matching the version of your Unity editor: master for the latest released LTS version and up to 2020.2, 2019.3 for up to 2019.4-LTS, 2018.3 for up to 2018.4-LTS and 2019.2, 2018.2, 2018.1, 2017.2 for up to 2017.4-LTS, 2017.1, 5.6.
You can use the package branch in Unity 2019.4 or newer in order to add this code to a project in the form of a package. For instructions please refer to the Setup section of the README file.

ダウンロードしたファイルを展開します。
f:id:bluebirdofoz:20210207232204j:plain

今回は以下の2つのスクリプトを利用します。
・Assets/Examples/Scripts/LocalNavMeshBuilder.cs
・Assets/Examples/Scripts/NavMeshSourceTag.cs
f:id:bluebirdofoz:20210207232214j:plain

MRTKプロジェクトの作成

MRTK 2.5をインポートして基本設定を行ったサンプルプロジェクトを準備します。
f:id:bluebirdofoz:20210207232227j:plain

今回はエディター上で動作確認を行いたいので、SpatialObjectMeshObserver で表示するメッシュを取り込みます。
f:id:bluebirdofoz:20210207232237j:plain

SpatialObjectMeshObserver の設定手順は以下の記事を参照ください。
bluebirdofoz.hatenablog.com

取り込んだメッシュで SpatialAwareness が動作することを確認します。
f:id:bluebirdofoz:20210207232255j:plain

取り込んだメッシュは NavMesh のアクセス対象となるため、読み込み/書き込み権限を与えておく必要があります。
3Dファイルの Inspector ビューを開き、[Read/Write Enabled]にチェックを入れておきます。
f:id:bluebirdofoz:20210207232306j:plain

NavMeshComponentsの取り込み

SpatialAwareness のメッシュに NavMesh の経路探索を行うスクリプトを取り込みます。
初めに NavMeshComponents から先述の2つのスクリプトを取り込みます。
・Assets/Examples/Scripts/LocalNavMeshBuilder.cs
・Assets/Examples/Scripts/NavMeshSourceTag.cs
f:id:bluebirdofoz:20210207232315j:plain

シーンに新規オブジェクトを作成し、LocalNavMeshBuilder コンポーネントを設定しておきます。
コンポーネントで設定した範囲内で経路探索が行われます。
f:id:bluebirdofoz:20210207232327j:plain

SpatialAwareness操作スクリプトの作成

SpatialAwareness に経路探索を行う NavMeshSourceTag コンポーネントを設定するスクリプトを作成します。
以下のようなスクリプトを作成しました。
・SpatialAwarenessNavMesh.cs

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

using Microsoft.MixedReality.Toolkit;
using Microsoft.MixedReality.Toolkit.SpatialAwareness;

namespace SpatialAwarenessNavMesh
{
    using SpatialAwarenessHandler = IMixedRealitySpatialAwarenessObservationHandler<SpatialAwarenessMeshObject>;

    public class SpatialAwarenessNavMesh : MonoBehaviour, SpatialAwarenessHandler
    {
        /// <summary>
        /// Value indicating whether or not this script has registered for spatial awareness events.
        /// このスクリプトが SpatialAwareness イベントに登録されているかどうかを示す値。
        /// </summary>
        private bool isRegistered = false;

        private void Start()
        {
            RegisterEventHandlers();
        }

        private void OnEnable()
        {
            RegisterEventHandlers();
        }

        private void OnDisable()
        {
            UnregisterEventHandlers();
        }

        private void OnDestroy()
        {
            UnregisterEventHandlers();
        }

        /// <summary>
        /// Registers for the spatial awareness system events.
        /// </summary>
        private void RegisterEventHandlers()
        {
            if (!isRegistered && (CoreServices.SpatialAwarenessSystem != null))
            {
                CoreServices.SpatialAwarenessSystem.RegisterHandler<SpatialAwarenessHandler>(this);
                isRegistered = true;
            }
        }

        /// <summary>
        /// Unregisters from the spatial awareness system events.
        /// </summary>
        private void UnregisterEventHandlers()
        {
            if (isRegistered && (CoreServices.SpatialAwarenessSystem != null))
            {
                CoreServices.SpatialAwarenessSystem.UnregisterHandler<SpatialAwarenessHandler>(this);
                isRegistered = false;
            }
        }

        /// <inheritdoc />
        public virtual void OnObservationAdded(MixedRealitySpatialAwarenessEventData<SpatialAwarenessMeshObject> eventData)
        {
            // Mesh追加時のイベント
            Debug.Log($"Tracking mesh {eventData.Id}");

            // NavMeshSourceTag をオブジェクトに追加
            eventData.SpatialObject.GameObject.AddComponent<NavMeshSourceTag>();
        }

        /// <inheritdoc />
        public virtual void OnObservationUpdated(MixedRealitySpatialAwarenessEventData<SpatialAwarenessMeshObject> eventData)
        {
            // Mesh更新時のイベント
            Debug.Log($"Update mesh {eventData.Id}");
            
            // NavMeshSourceTag をオブジェクトに追加
            NavMeshSourceTag tag = eventData.SpatialObject.GameObject.GetComponent<NavMeshSourceTag>();
            if (tag == null)
            {
                eventData.SpatialObject.GameObject.AddComponent<NavMeshSourceTag>();
            }
        }

        /// <inheritdoc />
        public virtual void OnObservationRemoved(MixedRealitySpatialAwarenessEventData<SpatialAwarenessMeshObject> eventData)
        {
            // Mesh削除時のイベント
            Debug.Log($"Remove mesh {eventData.Id}");
        }
    }
}

f:id:bluebirdofoz:20210207232343j:plain

作成したスクリプトをシーン内のオブジェクトに追加します。
f:id:bluebirdofoz:20210207232354j:plain

NavMeshの設定

プロジェクトに NavMesh の設定を行います。
メニューから[Window -> AI -> Navigation]を選択します。
f:id:bluebirdofoz:20210207232404j:plain

[Navigation]タグが追加され、[Scene]画面に[NavimeshDisplay]が表示されます。
[Show NavMesh]を有効化しておくと、シーン再生時に NavMesh の経路探索の結果を確認できます。
f:id:bluebirdofoz:20210207232415j:plain

動作確認

シーンを再生します。
SpatialAwareness のメッシュに NavMesh の経路探索の結果が青いフィールドで表示されていれば成功です。
f:id:bluebirdofoz:20210207232424j:plain

経路探索の設定変更

動的な経路探索の条件を変更する場合は[Navigation]ビューの[Agents]で設定を変更します。
f:id:bluebirdofoz:20210207232443j:plain

試しに半径と段差の乗り降りの値を小さく設定してみます。
f:id:bluebirdofoz:20210207232454j:plain

この状態でシーンを再生してみると、NavMesh の経路探索の結果が変わります。
小さな段差の上り下りが繋がらなくなっていることが分かります。
f:id:bluebirdofoz:20210207232506j:plain

次は HoloLens2 上で動作を確認してみます。
bluebirdofoz.hatenablog.com

参考ページ

tarukosu.hatenablog.com