[Unity] たった３分で移動AI？UnityのNavigation機能がスゴイ

先日 Unity の Navigation 機能について説明を求められる機会がありました。私自身、基本的に Navigation を利用するようなゲームを作らないので、 Navigation に関してはあまり触れたことがなく...。軽く触ってみたら、爆速で簡単な移動AIができて圧巻！ということで記事にしてみました。

[この記事の対象者] 
・Unity初級〜中級者
[この記事の目的]
・爆速で簡単な移動AIを作ろう

それでは始めていきましょう！



# ステージの作成

まずステージがないと始まらないのでステージを簡単に作っておきます。
今回はこんな感じ。
青が player 、赤が target となるオブジェクトです。
<img width="394" alt="スクリーンショット 2018-11-30 10.35.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/250456/593afcc8-cecb-2354-74c9-47c49138b700.png">



# 自動追従するAIの作成

青の player が赤の target まで、道に沿って移動するAI機能を作成します。

[操作]
1. player（自動で動かしたいもの）に **Nav Mesh Agent** という Component をアタッチします。
2. 次に、 Navigation ウィンドウで地形を **Bake** します。
3. スクリプトを書きます。
4. player オブジェクトにスクリプトをアタッチして、 Inspector から player, target　にそれぞれ対応するオブジェクトを入れます。

```PlayerMove.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class PlayerMove : MonoBehaviour {

	public NavMeshAgent player;
    public GameObject target;

	void Start () {
		player  = gameObject.GetComponent<NavMeshAgent>();
	}
	
	void Update () {
		if (target != null) {
            player.destination  = target.transform.position;
        }
	}
}
```

はい、これで自動追従AIの作成終了です！簡単！



# できた！と思いきや...

あれ、動かない...なんかエラーが出ている...
<img width="657" alt="スクリーンショット 2018-11-30 10.50.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/250456/bd321c39-edb7-0f36-eb58-66d6d549cad9.png">

Bake し忘れたかなー、と思ってもう一度 Bake して再生しても変わらず...

調べてみたら、どうやら通路や壁として使うオブジェクトは **Static** にチェック入れないとだめなんですね。Terrain はデフォルトで Static になってるので気づきませんでした。
<img width="463" alt="スクリーンショット 2018-11-30 11.41.13_1.png" src="https://qiita-image-store.s3.amazonaws.com/0/250456/f4bd2809-8c81-29a3-f8c5-7864b378229e.png">



[操作]
1. ステージに使用しているオブジェクト（床 Plane , 壁 Cube ）全てを Static に設定
2. 再度 Bake する

<img width="671" alt="スクリーンショット 2018-11-30 10.55.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/250456/0b18f78f-3cc3-38a2-9c64-c2180caf9b6b.png">
水色のエリアがちゃんと通路に沿って作られました！

再生すると、ちゃんと通路に沿って player が target を追いかけています。
![ezgif.com-video-to-gif.gif](https://qiita-image-store.s3.amazonaws.com/0/250456/d8b91e8f-03e0-656e-7486-5accbfdf5503.gif)

こんなに簡単に作れちゃうんですね！



# 障害物を避けて移動するAIの作成

さて続いて、次のステップに進みましょう。

ステージの形を少し変えます。
先ほどと同じく、青が player 、赤が target で、新たに加えた黄色のオブジェクトは obstacle （障害物）です。
<img width="417" alt="スクリーンショット 2018-11-30 11.00.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/250456/2eb32977-b8c3-6083-0a53-7cfbed48afa6.png">

ここでは、障害物を認識して、障害物のある通路を避けて迂回して target を追いかける移動AIを作成します。
これには、Nav Mesh Obstacle というものを使います。

[操作]
1. 黄色の obstacle （障害物となるオブジェクト）に **Nav Mesh Obstacle** という Component　をアタッチします。

これだけです！わずか3秒！



# またもや...

![ezgif.com-video-to-gif (1).gif](https://qiita-image-store.s3.amazonaws.com/0/250456/833e8689-0ecd-afdc-1ba8-0355139fd164.gif)
うーん？なんか違うな...

障害物のある通路を避けてくれず、行き詰まってしまいました。
調べてみると、 Nav Mesh Obstacle Component の Carve にチェックを入れると良いらしい。

[操作]
1. Nav Mesh Obstacle Component の **Carve** にチェックを入れる
<img width="457" alt="スクリーンショット 2018-11-30 11.50.20_1.png" src="https://qiita-image-store.s3.amazonaws.com/0/250456/95f26db7-4465-85d2-2195-5deb0cb75eb8.png">

<img width="826" alt="スクリーンショット 2018-11-30 11.09.22_1.png" src="https://qiita-image-store.s3.amazonaws.com/0/250456/46766b27-f215-c66f-9947-85c1e3b02a1d.png">
おや、水色の範囲が障害物周りだけなくなりました！

気を取り直して、この状態でもう一度再生。
![ezgif.com-video-to-gif (2).gif](https://qiita-image-store.s3.amazonaws.com/0/250456/71d17b1e-daf0-d274-ce4d-0df08bca0646.gif)

見事に迂回しました！



# 最後に

今回は以上です。
AIって、なんだか実装大変そうなイメージの項目。実際ゲームの企画をしている時にも、「敵どうする？」「AI必要じゃない？」「作るのムズそう」「NPC対戦やめて対戦プレイ形式にしよっか」みたいな話が出たりしました。

Unityなら、非常に簡単に、爆速で、移動AI作れます。
ぜひ試してみてください！


## 参考記事

[【Unity】NavMeshを学ぶ 障害物編 - うら干物書き](https://www.urablog.xyz/entry/2017/10/14/190557)
[NavMeshの使い方　その１ - テラシュールブログ](http://tsubakit1.hateblo.jp/entry/20120127/1327591104)
[NavMesh Obstacle の作成 - Unity User Manual](https://docs.unity3d.com/ja/current/Manual/nav-CreateNavMeshObstacle.html)