MRが楽しい

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

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

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

本記事は経路探索の結果を使って実際にモデルを動かしてみます。

前提条件

前回記事の続きです。
bluebirdofoz.hatenablog.com

移動するモデルを設定する

最初に経路探索の結果を使って移動する3Dモデルを準備します。
今回はモデルの方向の変化もわかるように以下の三角錐のモデルを準備しました。
f:id:bluebirdofoz:20210210225337j:plain

正面方向に先端を向けてモデルを配置します。
Nav Mesh Agent でモデルを移動させる場合はZ軸の正方向が正面になります。
f:id:bluebirdofoz:20210210225400j:plain

移動させたいオブジェクトの Inspector ビューを開き、[NavMeshAgent]を追加します。
f:id:bluebirdofoz:20210210225412j:plain

[NavMeshAgent]の設定項目は以下の通りです。

AgentType:利用する経路のエージェントタイプを指定します。
BaseOffset:アタリ判定(円筒)の高さのオフセットを設定します。
Steering
 Speed:動きの最高速度(単位:メートル/秒)を指定します。
 AngularSpeed:回転の回転の最高速度(単位:度/秒)を指定します。
 Acceleration:最高加速度(単位:メートル/秒の2乗)を指定します。
 StoppingDistance:エージェントが停止する目的地点までの設定距離を設定します。
 AutoBraking:有効時、目的地点の到着時にエージェントの移動速度が減速します。
ObstacleAvoidance
 Radius:エージェントの半径を指定します。障害物や他のエージェント間の衝突の計算に使用されます。
 Height:エージェントの高さを指定します。頭上にある障害物の下を通り抜ける計算に使用されます。
 Quality:障害物回避の品質を指定します。
 Priority:回避の優先度を指定します。高いほど優先度が択、エージェントはこの数値より低いエージェントを無視します。
PathFinding
 AutoTraverseOffMeshLine:有効時、オフメッシュリンクを自動で越えます。
 AutoRepath:有効時、エージェントは移動中に繰り返し経路探索を行います。目的地点への経路がない場合は最も近い到達可能場所への経路を作成します。
 AreaMask:エージェントが経路を探索する際にどのナビゲーションエリアとコストを利用するかを設定します。

docs.unity3d.com

前回記事と同様に経路をリアルタイムに表示したいので、[LineRenderer]を追加します。
f:id:bluebirdofoz:20210210225426j:plain

3Dモデルに合わせてアタリ判定の大きさや速度を調整しておきます。
f:id:bluebirdofoz:20210210225453j:plain

これらの[NavMeshAgent]を使って目的地点の設定と、[LineRenederer]を使って作成されたパスの表示を行う以下のスクリプトを作成しました。
・AgentMove.cs

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

using UnityEngine.AI;

[RequireComponent(typeof(NavMeshAgent))]
public class AgentMove : MonoBehaviour
{
    NavMeshAgent Agent;
    LineRenderer PathLineRenderer;

    void Start()
    {
        // 各コンポーネントの参照を取得する
        PathLineRenderer = GetComponent<LineRenderer>();
        Agent = GetComponent<NavMeshAgent>();
    }

    void Update()
    {
        // 経路のパスを取得する
        Vector3[] positions = Agent.path.corners;

        // パスを取得できたか確認する
        if (positions.Length > 1)
        {
            // 経路のパスをラインレンダラーで描画する
            PathLineRenderer.positionCount = positions.Length;
            for (int i = 0; i < positions.Length; i++)
            {
                Debug.Log("point " + i + "=" + positions[i]);
                // ラインをパスの位置から50cm上げた位置に配置する
                Vector3 linePos = new Vector3(positions[i].x, positions[i].y + 0.5f, positions[i].z);
                PathLineRenderer.SetPosition(i, linePos);
            }
        }
    }

    public void SetGoal(Transform a_transform)
    {
        //目的地となる座標を設定する
        Agent.destination = a_transform.position;

        Debug.Log("SetAgent");
    }
}

f:id:bluebirdofoz:20210210225505j:plain

作成したスクリプトをオブジェクトにアタッチします。
f:id:bluebirdofoz:20210210225516j:plain

最後にタップオブジェクトのイベントで、スクリプトの目的地を指定する関数の呼び出しを登録して準備は完了です。
f:id:bluebirdofoz:20210210225526j:plain

動作確認

シーンを再生して動作を確認します。
タップで示したポイントに3Dモデルが移動すれば成功です。
f:id:bluebirdofoz:20210210225539j:plain

続けてタップすることで目的地点が更新され、3Dモデルが移動し続けます。
f:id:bluebirdofoz:20210210225549j:plain