NavMeshを使った移動



概要

NavMeshを使用したObjectの初歩的な移動方法を紹介します。
NavMeshを作成されていない方、用意されていない方はこちらで作成を行ってください。

環境

Unity 2018.3.8.f1

NavMeshAgentコンポーネント

NavMeshをオブジェクトが利用するには「NavMeshAgent」コンポーネントがを必要です。
このNavMeshAgentコンポーネントはInspectorのAddComponentのNavigation項目にあります。
※今回の移動ではComponentの値を変更することはないので
 項目の説明は別で行います。

unity_0206

スクリプト実装

コンポーネントの設定が完了したら次はスクリプトの実装を行います。
スクリプト側ではNavMeshAgentに移動先の設定し、
1つのメソッドを実行するだけで、目的地まで移動します。

UnityEngine.AI

NavMeshAgentクラスは「UnityEngine.AI」に含まれていますので、
以下のようにusingを使用します。
using UnityEngine.AI;
usingを使用しない場合はクラス名の前に「UnityEngine.AI.」を追加して下さい。
UnityEngine.AI.NavMeshAgent nav_mesh_agent;

移動先の取得

スクリプトの必要な情報としてまずは移動先の座標です。
この座標はオブジェクトから取得しても、直接指定もかまいません。
今回は移動先となるオブジェクトから座標を取得する方法をとっています。

[SerializeField]
GameObject TargetObject;	// 移動予定地のオブジェクト

移動開始

移動先が決まったらNavMeshAgentの「SetDestination」を使用して移動を開始します。
このメソッドは移動開始時に1度指定するだけで問題ありません。
それ以降はNavMeshAgentが自動でオブジェクトを目的地まで移動させ続けます。
以下のようにStartメソッドで指定しても目的地まで移動します。

void Start()
{
	NavMeshAgent nav_mesh_agent = GetComponent<NavMeshAgent>();
	// 移動先の決定
	nav_mesh_agent.SetDestination(TargetObject.transform.position);
}

移動量の取得

オブジェクトが移動しているかどうかはNavMeshAgentのvelocity.magnitudeで確認できます。
「velocity.magnitude」が0よりも大きければ移動しています。
Animatorで移動中、停止中の切り替えを行いたい場合はこちらの値を
利用すると切り替えが可能となります。
NavMeshAgent nav_mesh_agent = GetComponent<NavMeshAgent>();

GetComponent<Animator>().SetFloat("Speed", nav_mesh_agent.velocity.magnitude);

ナビゲーションの停止

SetDestinationを実行すると自動で目的地に向かいますが、
途中で移動を止めたいケースが発生することがあります。
その時はNavMeshAgentの「isStopped」の値を変更します。
trueがナビゲーションOFF、falseがナビゲーションONです。
GetComponent<NavMeshAgent>().isStopped = true;

到達の判定

目的の場所に到達したかどうかの判定方法はいくつかあります。
例えば「当たり判定を使用する」または「距離を測る」などです。

当たり判定を使う

当たり判定を使う場合、到達予定の場所にColliderのついた
オブジェクトを配置して、重なりか衝突のEnterのメソッドで判定を行います。
※Agentを設定しているオブジェクトにもColliderが必要です。

private void OnTriggerEnter(Collider other)
{
	if (other.tag == "Goal")
	{
		NavMeshAgent nav_mesh_agent = GetComponent<NavMeshAgent>();
		nav_mesh_agent.isStopped = true;
		GetComponent<Animator>().SetBool("Win", true);
	}
}

距離を測る

NavMeshAgentには設定されている目的地までの距離が保存されている
「remainingDistance」があります。
この値が0になったら目的地に到達していることになります。
※remainingDistanceは距離が不明の場合はInfinityを返しますが
 この値を返す頻度が高いので気を付けてください。

void Update()
{
	NavMeshAgent nav_mesh_agent = GetComponent<NavMeshAgent>();
	if (nav_mesh_agent.remainingDistance == 0.0f)
	{
		GetComponent<Animator>().SetBool("Win", true);
	}
	else
	{
		GetComponent<Animator>().SetFloat("Speed", nav_mesh_agent.velocity.magnitude);
	}
}