【Unity 2022.2 以降】AIナビゲーションの基本的な使い方
現在制作中のUO・MoE風スキル制アクションゲームで「プレイヤーを感知した敵が、障害物を避けつつ自動で近づいてくる」というよくある処理をUnityで実装しようとしました。しかし、どうやらバージョン 2022.2 でAIナビゲーション周りが大きく変わったらしく、検索しても初心者向けの記事が見つかりませんでした。そこで今回は、ゲーム制作をはじめたばかりの人向けに、AIナビゲーションの基本的な使い方を紹介していきたいと思います。
目次
AIナビゲーションの使い方
1.AIナビゲーション用のパッケージを導入する
2022.2 以降のバージョンでAIナビゲーション機能を使いたい場合は Package Manager から専用のパッケージをインストールする必要があります。この項目では、Package Manager から AI Navigation をインストールしてAIナビゲーション機能を使えるようにする方法を紹介します。
AIナビゲーション用のパッケージ導入手順
- メニューの Window > Package Manager を選択します。
- Package Manager ウィンドウ左上のプルダウンをクリックして Unity Registry を選択します。
- Packages の中から AI Nagigation を選択して画面右上の Install ボタンをクリックします。
インストールが完了するとAIナビゲーションが使えるようになります。
2.自動移動させたいエージェントの情報を登録する
一言で自動移動と言っても、キャラクターの大きさや「空を飛べる」「水の中しか移動できない」などの特徴によって通れるルートが変わってきます。この項目では、ナビゲートしたいキャラクター種別(エージェント)を登録する方法を紹介します。
エージェント情報の登録手順
- メニューの Window > AI > Navigation を選択します。
- デフォルトで Humanoid エージェントが登録されているので、ここでは飛行タイプのエージェントを登録していきます。Agent Types の右下にある + ボタンをクリックします。
- 各項目を以下のように設定します。
- Name:Flying
- エージェントの名前です。分かりやすい名前を設定します。
- Radius:1
- エージェントの半径で、エージェントが通れる道幅が決まります。鳥をイメージしているので、翼の分だけ大きく設定しています。
- Height:0.5
- エージェントの高さで、エージェントが通れる道の高さが決まります。鳥をイメージしているので少し小さく設定しています。
- Step Height:0.49
- エージェントが移動できる段差の高さが決まります。鳥に段差は関係ないので100を設定したいところですが、エージェントの高さ以上の値を設定すると後々 Warning が出てしまうので0.49を設定しています。
- Max Slope:36
- エージェントが移動できる傾斜の角度が決まります。鳥に傾斜は関係ないので最大の60を設定したいところですが、こちらも Warning が出てしまうので36を設定しています。
- Generated Links:オフメッシュリンク(後の項目で出てきます)を自動生成するときに使う設定です。
- Drop Height:0
- オフメッシュリンクはここでは使わないので0のままにしています。
- Jump Distance:0
- オフメッシュリンクはここでは使わないので0のままにしています。
飛行タイプのエージェントを登録することができました。
3.エージェントのルートを事前計算して結果を保存する
Unityでは、エージェントのルートを事前にある程度計算しておくことで負荷を下げるような仕組みなっています。この項目では、エージェントのルートを事前計算して結果を保存する(ベイクする)方法を紹介します。
ルートのベイク手順
- 地形を作成します。今回は Level というゲームオブジェクトの下に Walkable というゲームオブジェクトを作成して、その中に地形を作成しています。
- Hierachy ウィンドウの Level ゲームオブジェクトを選択します。
- まずは Humanoid のルートを計算します。Inspector ウィンドウの Add Component ボタンを押してから NavMeshSurface をクリックします。
- 各項目を以下のように設定します。
- Agent Type:Humanoid
- ルートを事前計算するエージェントです。Humanoid を選択します。
- Degault Area:Walkable
- 事前計算で使用するデフォルトの地形情報(後の項目で出てきます)です。ここではデフォルトの Walkable を選択します。
- Generate Links:オフ
- オフメッシュリンクを自動生成する場合はオンにします。今回は自動生成しないのでオフにします。
- Use Geometry:Render Meshes
- ベイクに使用するジオメトリです。メッシュとコリジョンから選べますが、特に拘りがないので今回はデフォルトのメッシュを選択しています。
- Object Collection:事前計算のときに加味するオブジェクトの設定です。
- Collect Objects:Current Object Hierarchy
- 事前計算のときに加味するオブジェクトです。画面左側に配置したエージェント(緑と青の円柱)と画面右側に配置したゴール(赤い立方体)を障害物として扱いたくないので、今回は Current Object Hierarchy を選択します。
- All Game Objects:アクティブなゲームオブジェクトをすべて加味します。
- Volume:指定した範囲内のアクティブなゲームオブジェクトだけを加味します。
- Current Object Hierarchy:NavMeshSurface を追加したゲームオブジェクトとその子孫オブジェクトだけを加味します。
- NavMeshModifier Component Only:NavMeshModifier Component(後の項目で出てきます)だけを加味します。
- Include Layers:Everything
- 計算対象をレイヤーで絞り込みたい場合に設定します。今回は絞り込まないので Everything を選択します。
- NavMeshSurface コンポーネント右下の Bake ボタンをクリックします。
- 同様の手順で Flyable のルートを計算します。Inspector ウィンドウの Add Component ボタンを押してから NavMeshSurface をクリックします。
- 各項目を以下のように設定します。
- Agent Type:Flyable
- Degault Area:Walkable
- Generate Links:オフ
- Use Geometry:Render Meshes
- Object Collection:
- Collect Objects:Current Object Hierarchy
- Include Layers:Everything
- NavMeshSurface コンポーネント右下の Bake ボタンをクリックします。
各エージェントのルートを事前計算できました。
4.オブジェクトを自動移動させる
ここまでの手順でキャラクターを自動移動させる準備が整いました。この項目では、オブジェクトを自動移動させる設定方法と簡単なサンプルコードを紹介します。
オブジェクトを自動移動させる設定手順
- 自動移動させるゲームオブジェクトを作成します。今回は Agent というゲームオブジェクトの下に Humanoid と Flying の2つを作成しています。
- まずは Humanoid を自動移動させていきます。Hierachy ウィンドウの Humanoid ゲームオブジェクトを選択します。
- Inspector ウィンドウの Add Component ボタンを押してから NavMeshAgent をクリックします。
- 各項目を以下のように設定します。
- Agent Type:Humanoid
- 使用するエージェントです。Humanoid を選択します。
- Base Offset:1
- エージェントの基準となる高さです。Transform > Position > Y の値にあわせて1を設定しています。
- Steering:エージェントの移動に関する項目です。
- Speed:3.5
- エージェントの移動速度です。デフォルトの3.5を設定しています。
- Angular Speed:120
- エージェントの回転速度です。デフォルトの120度を設定しています。
- Acceleration:8
- エージェントの加速度です。デフォルトの8を設定しています。
- Stopping Distance:0
- 目標地点からどれくらいの距離に入ったら停止するかを表します。目標地点ぴったりに止まって欲しいので0を設定しています。
- Auto Braking:オン
- 目標地点に近づいたら自動的に速度を抑えるかの設定です。自動で停止してほしいのでオンにしています。
- Obstacle Avoidance:障害物の回避に関する設定です。
- Radius:0.5
- 障害物にどれだけ近づけるかを表す相対距離です(オブジェクトのScaleで変化します)。0.5を設定します。
- Height:2
- どれくらいの高さの障害物までくぐれるかを表す相対的な高さです(オブジェクトのScaleで変化します)。2を設定します。
- Quality:High Quality
- 障害物を回避する計算のクオリティです。高いほど障害物を回避しやすくなりますが、その分計算コストがかかります。今回はデフォルトの High Quality を選択しています。
- Priority:50
- 他のエージェントを回避するかの判定に使用します。この数値より大きい値が設定されたエージェントは避けずに無視するようになります。今回はデフォルトの50にしています。
- Path Finding:エージェントがルート計算する際の設定です。
- Auto Traverse Off Mesh Link:オン
- オフメッシュリンクを自動で使うかの設定です。今回はオフメッシュリンクを使用しないのでデフォルトのオンにしています。
- Auto Repath:オン
- 計算したルートが使えなくなったときに新しいルートを再計算するかを表します。再計算してほしいのでオンにしています。
- Area Mask:Everything
- ルート計算に使用する地形種別です。今回はすべての地形を使ってほしいので Everything を選択します。
- 同様の手順で Flying を自動移動させていきます。Hierachy ウィンドウの Flying ゲームオブジェクトを選択します。
- Inspector ウィンドウの Add Component ボタンを押してから NavMeshAgent をクリックします。
- 各項目を以下のように設定します。
- Agent Type:Flying
- Base Offset:4
- 空に浮かせたかったので大きい値にしています。
- Steering:
- Speed:3.5
- Angular Speed:120
- Acceleration:8
- Stopping Distance:0
- Auto Braking:オン
- Obstacle Avoidance:
- Radius:0.5
- Height:8
- 空に浮かせたかったので大きい値にしています。
- Quality:High Quality
- Priority:50
- Path Finding:
- Auto Traverse Off Mesh Link:オン
- Auto Repath:オン
- Area Mask:Everything
サンプルコードの紹介と設定手順
今回は、画面右上の標的に向かって自動移動するようにしていきます。AgentScript という名前のC#スクリプトを作成して、↓のコードをコピー&ペーストしてください。
using System.Collections;using System.Collections.Generic;using UnityEngine;public class AgentScript : MonoBehaviour{public UnityEngine.AI.NavMeshAgent navMeshAgent;public GameObject goal;// Start is called before the first frame updatevoid Start(){navMeshAgent.SetDestination(goal.transform.position);}// Update is called once per framevoid Update(){}}
作成したら、自動移動させるゲームオブジェクトにスクリプトを設定していきます。
- まずは Humanoid にスクリプトを設定します。Hierachy ウィンドウの Humanoid ゲームオブジェクトを選択します。
- Inspector ウィンドウの Add Component ボタンを押してから AgentScript をクリックします。
- 追加したコンポーネントの NavMeshAgent の箇所に Humanoid ゲームオブジェクトをドラッグ&ドロップします。
- 追加したコンポーネントの Goal の箇所にゴール用のゲームオブジェクトをドラッグ&ドロップします。
- 同様の手順で Flying にスクリプトを設定します。Hierachy ウィンドウの Flying ゲームオブジェクトを選択します。
- Inspector ウィンドウの Add Component ボタンを押してから AgentScript をクリックします。
- 追加したコンポーネントの NavMeshAgent の箇所に Flying ゲームオブジェクトをドラッグ&ドロップします。
- 追加したコンポーネントの Goal の箇所にゴール用のゲームオブジェクトをドラッグ&ドロップします。
ゲームオブジェクトがゴールに自動移動するようになりました。
5.ルートのリアルタイム計算で使う障害物を設定する
ゲームによっては「プレイ中に障害物を出現させて、キャラクターは障害物を迂回して移動するようにしたい」というケースもあるかと思います(スイッチを押したら壁が出現して通行不能になる等)。この項目では、ベイクの時に存在しないオブジェクトを障害物として設定する方法を紹介します。
障害物の設定手順
- 障害物用のゲームオブジェクトを追加します。今回は Obstacle という名前で作成しています。
- Hierachy ウィンドウの Obstacle ゲームオブジェクトを選択します。
- Inspector ウィンドウの Add Component ボタンを押してから NavMeshObstaclet をクリックします。
- 各項目を以下のように設定します。
- Shape:Capsule
- 障害物の形状です。今回は球体なので Capsule にしています。
- Center:0, 0, 0
- 障害物の中心座標です。今回は球体なので 0,0,0 にしています。
- Size:障害物の大きさです。
- Radius:0.5
- 障害物の相対的な半径です(オブジェクトのScaleで変化します)。0.5を設定します。
- Height:1
- 障害物の相対的な高さです(オブジェクトのScaleで変化します)。1を設定します。
- Carve:オン
- 障害物のまわりの NavMesh をくり抜くかです。くり抜かないとエージェントがスタックしてしまうのでオンにします。
- Move Threshold:0.1
- 障害物を静止状態として扱う閾値です。この値より移動速度が小さい場合は静止状態として扱います。デフォルトの0.1を設定しています。
- Time To Stationary:0.5
- 静止扱いするまでの時間(秒)です。Move Threshold よりも移動速度が小さい状態が何秒続いたら静止扱いするかを表します。デフォルトの0.5を設定しています。
- Carve Only Stationary:オン
- このチェックがオンだと、静止状態の間だけまわりの NavMesh をくり抜きます。オフにすると計算コストがかかるのでオンにします。
ゲームオブジェクトが障害物を避けるようになりました。
(おまけ1)特殊な地形を追加する
ゲームによっては「特殊な地形を作って迂回させたりしたい」というケースもあるかと思います。この項目では、新しい地形(エリアと言います)を登録して NavMesh に反映する方法を紹介します。
エリアの登録手順
まずは新しいエリアを登録します。通るのが困難な砂地用のエリアを登録していきます。
- メニューの Window > AI > Navigation を選択します。
- Navigation ウィンドウ上部の Areas ボタンをクリックします。
- User 6の欄(色が砂地っぽいので)に以下のように入力します。
- Name:Sand
- エリア名です。分かりやすい名前を設定します。
- Cost:100
- エリアを通るのに要するコストです。数値が高いほど自動移動のルートに選ばれにくくなります。
砂地用のエリアが登録されました。
NavMesh への反映手順
次に登録したエリアを NavMesh に反映します。
- Hierachy ウィンドウを右クリックして AI > NavMesh Modifier Volume を選択します。
- 作成されたゲームオブジェクトを Level の下に移動します。
- 作成されたゲームオブジェクトの Transform を変更してエリアを反映したい場所に移動します。
- NavMesh Modifier Volume コンポーネントの各項目を以下のように設定します。
- Size:4, 3, 4
- 反映する地形の大きさです。デフォルトの値をそのまま使用しています。
- Center:0, 1, 0
- 反映する地形の中心です。デフォルトの値をそのまま使用しています。
- Area Type:Sand
- 反映する地形種別です。先ほど作成した Sand を選択します。
- Affected Agents:All
- エリア情報を反映するエージェントです。今回はすべてのエージェントを対象にしたいので All を選択します。
- Hierachy ウィンドウで Level ゲームオブジェクトを選択します。
- NavMesh Surface コンポーネント2つの Bake ボタンをクリックします。
エージェントが砂地を避けるようになりました。
(おまけ2)特定のエージェントにだけ影響する障害物を追加する
ゲームによっては「特定のエージェントだけ通れないような障害物を作りたい」というケースもあるかと思います。この項目では、特定のエージェントにだけ影響する障害物を追加する方法を紹介します。
特定のエージェントにだけ影響する障害物の設定手順
今回は、飛行タイプだけ素通りできるような障害物を設定していきます。
- 障害物を作成します。今回は Level というゲームオブジェクトの下に Block という障害物を作成しています。
- Hierachy ウィンドウの Block ゲームオブジェクトを選択します。
- Inspector ウィンドウの Add Component ボタンを押してから NavMeshModifier をクリックします。
- 各項目を以下のように設定します。
- Mode:Remove object
- オブジェクトの情報をどう取り扱うかを表します。今回は Flying だけ無視させたいので Remove object を選択します。
- Affected Agents:Flying
- どのエージェントに影響を与えるかを表します。今回は Flying だけ無視させたいので Flying を設定します。
- Apply To Children:オン
- 子オブジェクトも同様に取り扱うかを表します。今回は子オブジェクトがないのでどちらでも構いません。
- Hierachy ウィンドウで Level ゲームオブジェクトを選択します。
- NavMesh Surface コンポーネント2つの Bake ボタンをクリックします。
Humanoid エージェントの上ルートが塞がれてしまったので砂地を通るようになりました。
(おまけ3)ショートカットを追加する
ゲームによっては「特定のエージェントだけ通れるショートカットを作りたい」というケースもあるかと思います。この項目では、特定のエージェントだけ通れるショートカットを追加する方法を紹介します。
特定のエージェントだけ通れるショートカットの追加手順
今回は、Humanoid タイプだけ通れるショートカットを作成していきます。
- Hierachy ウィンドウを右クリックして AI > NavMesh Link を選択します。
- 作成されたゲームオブジェクトの Transform を変更してショートカットの開始位置に移動します。
- NavMesh Link コンポーネントの各項目を以下のように設定します。
- Agent Type:Humanoid
- ショートカットを利用できるエージェント種別です。Humanoid を選択します。
- Start Point:0, 0, 0
- ショートカットのスタート地点です。0, 0, 0 を設定します。
- End Point:8.5, 0, 0
- ショートカットのゴール地点です。8.5, 0, 0 を設定します。
- Width:0
- ショートカットの幅です。デフォルトの0を設定しています。
- Cost Modifier:-1
- ショートカットを通過する際のコストです。正の値を指定するとショートカットの長さに応じたコストがかかるようになります。ショートカットを積極的に使ってほしいので-1を設定しています。
- Auto Update Position:オフ
- ゲームオブジェクトの Transform、NavMesh Link のスタート地点、NavMesh Link のゴール地点のいずれかが変更されたときに、ショートカットのスタート地点とゴール地点を自動で再計算するかを表します。スクリプトで変化させたりしないのでオフにしています。
- Bidirectional:オン
- スタート⇒ゴールだけでなくゴール⇒スタートのショートカットも許可するかを表します。ゴール⇒スタートのショートカットもさせたいのでオンにしています。
- Area Type:Walkable
- ショートカットのエリアタイプを表します。ショートカットを積極的に使ってほしいので Walable を設定しています。
Humanoid エージェントがショートカットを使うようになりました。
おわりに
以上、ゲーム制作をはじめたばかりの人向けに、Unity 2022.2 以降でのAIナビゲーションの基本的な使い方を紹介させていただきました。今回紹介した方法を組み合わせていけば、キャラクターをかなり自由に動かせるようになるのではないかなと思います。少しでも皆さんの参考になれば幸いです。