【Unity】NavMeshで敵キャラが自キャラを追跡するようにする

NavMesh.png

 敵キャラが自キャラを追跡する最も簡単なロジックは、「自キャラに向かって敵キャラを移動させること」だと思います。すると大抵の場合、自キャラとの間にある障害物に引っかかってしまい、動けなくなってしまうことでしょう。そういうゲームならいいんですが、できればもう少しスマートに移動させたいですよね。

 Unityには、目標地点までの経路探索を行う「NavMesh」という仕組みがあります。NavMeshでは下記の特徴を持っています。
  • エージェント(動かすキャラ)の大きさや登れる坂の角度などを設定できる
  • ステージの凹凸や障害物の情報から動ける範囲(ポリゴン)を予め計算する。この処理をベイクと呼ぶ
  • NavMesh Agentコンポーネントに目標地点を指定すると、ベイクされたポリゴンを通って移動する
  • たどり着けない場合は、できるだけ近づいて停止する
準備として、Terrainフィールド上に自キャラと敵キャラを配置します。
ざっくりこんなイメージです。

NavMesh1.png


NavMeshをベイクする

NavMesh2.png

Window > AI > Navigation を選択して、Navigationウィンドウを開きます。

NavMesh3.png

Bakeタブを選択後、Bakeボタンを押します。
この処理は非常に時間がかかります。
ベイクが完了すると、移動可能な範囲が青く表示されます。

敵キャラに自キャラを追跡させる

1) 自キャラに「Player」タグを設定します。
 Inspector上部のTagプルダウン > Player

2) 敵キャラにNavMesh Agentをアタッチします。
 Add Component > NavMeshAgent

3) Inspector上で移動性能を設定します。
 ・Speed = 移動速度
 ・Angular Speed = 回転速度
 ・Acceleration = 加速度

4) 目的地を指定するスクリプトを用意します。
using UnityEngine;
using UnityEngine.AI;

[RequireComponent(typeof(NavMeshAgent))]
public class EnemyMove : MonoBehaviour
{
private NavMeshAgent _agent;

void Start()
{
_agent = GetComponent<NavMeshAgent>();
}

public void OnDetectObject(Collider collider)
{
// 検知オブジェクトがPlayerなら追いかける
if (collider.CompareTag("Player"))
{
_agent.destination = collider.transform.position;
}
}
}
EnemyMove.cs とします。

5) 敵キャラにEnemyMove.csをアタッチします。
 まだ自キャラの検知ができていないので動きません。
 次に自キャラ検知機能を作っていきます。

6) 敵キャラに自キャラ検知用Colliderをセットします。
 ・敵キャラに空の子オブジェクトを追加
 ・名前を「CollisionDetector」にする
 ・CollisionDetectorにSphire Colliderをアタッチ
 ・isTriggerにチェック

7) 自キャラ検知用スクリプトを用意します。
using UnityEngine;
using UnityEngine.Events;

[RequireComponent(typeof(Collider))]
public class CollisionDetector : MonoBehaviour
{
[SerializeField] private TriggerEvent onTriggerStay = new TriggerEvent();

private void OnTriggerStay(Collider other)
{
onTriggerStay.Invoke(other);
}

[Serializable]
public class TriggerEvent : UnityEvent
{
}
}
CollisionDetector.cs とします。

8) 衝突検知スクリプトをアタッチします。
 ・敵キャラ内にあるCollision Detectorオブジェクトに Collision Detector.cs をアタッチ
 ・OnTriggerStayの+ボタンを押す
 ・オブジェクト欄に敵キャラを指定
 ・EnemyMoveスクリプトのOnDetectObject(2つあるが引数なしの方)を選択

正しく設定するとこの通り。
NavMesh4.png

これで実行すると、自キャラが検知コライダーに触れるまで近づくと、敵キャラが自キャラを目指して移動を開始します。
そして、敵キャラの検知コライダーから出る(振り切る)とそこで停止します。

ゲーム中に変化する障害物

NavMeshは事前に計算された経路を辿る機能ですが、開閉するドアや落石による障害物などを即時に反映させることができます。
これらの障害物に NavMeshObstacle コンポーネントをアタッチして、Carveにチェックを付けるだけです。
是非試してみて下さい。


今回は3Dゲームにおいて非常に重要な追跡ロジックを紹介しました。
近いうちに発展版として「敵の視野設定」を記事にしたいと思います。


ゲームのアンテナ