NavMeshを使った移動

環境

Unity 2018.3.8.f1

概要

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

NavMeshコンポーネント

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

unity_0206

スクリプト実装

コンポーネントの設定が完了したら次はスクリプトの実装を行います。
スクリプト側ではNavMeshAgentに移動先の設定をするだけです。

移動先の取得

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

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

移動開始

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

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

移動量の取得

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

到達の判定

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

当たり判定を使う

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

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

距離を測る

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

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