Unity 6|NavMesh Agentで2D風の追いかけっこゲームを作ろう!公式機能だけで障害物を避ける敵AI
2Dの見下ろし型ゲームのような画面で、敵がプレイヤーを追いかける。間に壁があっても、敵は通れる道を探して回り込む。今回はUnity公式のAI NavigationとNavMesh Agentだけで、その仕組みを作ります。非公式のNavMeshPlusは使いません。
1. なぜ3DのNavMeshで「2D風」が作れるの?
Unityの標準NavMeshは、主に3D空間の経路探索を想定した機能です。ただし、ゲームの内部構造と画面上の見え方は別物。XZ平面に3Dの地面と壁を置き、Orthographic(平行投影)カメラで真上から見下ろすと、2Dゲームのような画面にできます。

| 通常の2Dゲーム | 今回の2D風ゲーム | |
|---|---|---|
| 画面の左右 | X | X |
| 画面の上下 | Y | Z |
| 高さ | Z | Y |
| 地面 | XY平面 | XZ平面 |
| 経路探索 | 別の設計・実装が必要 | 標準NavMeshを利用 |
2. 地面と壁を配置する
Unity 6で新規3Dプロジェクトを作ります。プロジェクト名の例は NavMeshChaseGame。
Hierarchyで 3D Object → Plane を作成して Ground に改名します。TransformはPosition (0,0,0)、Rotation (0,0,0)、Scale (1,1,1)。PlaneはXZ平面に広がり、初期状態で約10×10の広さです。
続いて 3D Object → Cube を作り Wall に改名。TransformはPosition (0,0.5,0)、Rotation (0,0,0)、Scale (1,1,5) にします。壁の両端には迂回できる隙間が残ります。CubeのBox Colliderはそのままにします。
3. プレイヤーと敵を作る
空のGameObjectを Player と名付け、Positionを (3,0,-3) にします。子にCapsuleを作って Visual と名付け、子のローカルPositionを (0,1,0) にします。
同様に空の Enemy を作成し、Positionを (-3,0,3) にします。子のCapsule Visual のローカルPositionも (0,1,0)。識別しやすいように敵の見た目を赤色にしてもよいでしょう。
SampleScene
├─ Main Camera
├─ Directional Light
├─ Ground (Plane)
├─ Wall (Cube)
├─ Player
│ └─ Visual (Capsule)
└─ Enemy
└─ Visual (Capsule)
親のPositionは地面上の位置です。子のVisualを使うことで、見た目だけあとからSpriteに交換できます。
4. AI Navigationをインストールする
NavMeshを作る(Bakeする)には、公式のAI Navigationパッケージが必要です。このパッケージには、NavMesh Surfaceなど、歩ける場所を作る公式コンポーネントが含まれています。
まず、すでに入っているか確認しましょう。
Window → Package Management → Package Managerを開く- 左上の表示を In Project にする
- AI Navigation が一覧にあれば、インストールは不要
一覧になければ、次の手順で入れます。
- 表示を Unity Registry に切り替える
- AI Navigation を選び、
Installを押す
ポイント: 次の章で使うNavMesh Surfaceは、このパッケージの機能です。入っていないと、Add Componentで検索しても出てきません。Enemyに付けるNavMesh Agentは、Unity本体の機能なので、パッケージがなくても使えます。ただし、Bakeしていないと、敵は動きません。
5. NavMesh Surfaceで歩ける場所を作る
空のGameObject Navigation を作成し、NavMesh Surface コンポーネントを追加します。初期の小規模サンプルでは次を目安にします。
| 設定 | 値 |
|---|---|
| Agent Type | Humanoid(既定のAgent Type) |
| Collect Objects | All(表示名はパッケージ版で異なる場合あり) |
| Use Geometry | Render Meshes |
| Include Layers | Everything |
Bake を押すと、地面を移動可能なNavMeshとして生成します。Sceneビューで移動可能領域を確認しましょう。壁の位置には通れない部分ができ、両端には迂回できる領域が残るはずです。

ポイント: Bakeは現在の静的な形状をもとに経路探索用の領域を作ります。後から壁の配置を変えたときは、必要に応じてBakeし直してください。移動する障害物は別途NavMesh Obstacleなどを検討します。
6. 敵にNavMesh Agentを設定する
Enemy に NavMesh Agent を追加します。最初は次の設定で試せます。
| 設定 | 値 |
|---|---|
| Agent Type | NavMesh Surfaceと同じHumanoid |
| Speed | 3 |
| Angular Speed | 360 |
| Acceleration | 8 |
| Stopping Distance | 1 |
| Radius | 0.3 |
| Height | 2 |
Stopping Distance は目標にどれだけ近づいて停止するかの目安です。Agent TypeがSurfaceと一致することが重要です。
7. 追いかけるスクリプト
EnemyChase.cs を作ります。
using UnityEngine;
using UnityEngine.AI;
[RequireComponent(typeof(NavMeshAgent))]
public class EnemyChase : MonoBehaviour
{
[SerializeField] private Transform player;
private NavMeshAgent agent;
void Start()
{
agent = GetComponent<NavMeshAgent>();
}
void Update()
{
if (player == null || !agent.isOnNavMesh)
{
return;
}
agent.SetDestination(player.position);
}
}
Enemyにアタッチし、Inspectorの Player 欄にHierarchyのPlayerをドラッグ&ドロップします。
GetComponent<NavMeshAgent>() は同じGameObjectのNavMesh Agentを取得します。SetDestination(player.position) でプレイヤーの現在位置を目的地に指定します。実際の経路計算には数フレームかかる場合があります。isOnNavMesh はAgentがNavMesh上に配置されているか確認するプロパティです。
ここでは初学者向けに毎フレーム目標を更新しています。大規模なゲームでは更新頻度を下げる設計も検討してください。
8. Input Systemでプレイヤーを動かす
Input Systemパッケージを導入し、必要に応じてProject SettingsのActive Input Handlingを Input System Package (New) または Both にします。Playerに PlayerMove.cs を追加します。
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerMove : MonoBehaviour
{
[SerializeField] private float moveSpeed = 3f;
void Update()
{
if (Keyboard.current == null) return;
Vector3 direction = Vector3.zero;
if (Keyboard.current.leftArrowKey.isPressed) direction.x -= 1;
if (Keyboard.current.rightArrowKey.isPressed) direction.x += 1;
if (Keyboard.current.upArrowKey.isPressed) direction.z += 1;
if (Keyboard.current.downArrowKey.isPressed) direction.z -= 1;
transform.position += direction.normalized * moveSpeed * Time.deltaTime;
}
}
上下移動に使っているのはYではなくZです。これはゲームの地面がXZ平面だからです。normalized で斜め移動時の速度が過度に大きくならないようにします。
注意: このコードは移動の最小例で、壁との衝突や地面から出ないための制限を実装していません。実際に遊べるゲームではCharacterControllerなどで壁の通り抜けを防ぐ必要があります。
9. 真上から映すカメラを設定する
Main Cameraを選び、次を設定します。
| 設定 | 値 |
|---|---|
| Position | (0,15,0) |
| Rotation | (90,0,0) |
| Projection | Orthographic |
| Size | 7 |
Orthographic は平行投影です。遠い物体ほど小さく見えるPerspectiveとは違い、距離によって見かけの大きさが変化しません。

Playを押し、矢印キーでPlayerを壁の向こう側へ動かしてみましょう。Bakeが正しくできていれば、EnemyはNavMesh上の通れる道を探して追跡します。
10. CapsuleをSpriteに変えるには?
Enemy/Visual のCapsuleの代わりにSpriteRendererを持つ子GameObjectを配置することもできます。通常のSpriteはXY平面に表示されるため、子VisualのRotationを (90,0,0) などに調整して真上から見えるようにします(画像の向きに応じて調整)。NavMesh Agentは親Enemyに付けたままです。
SpriteRendererは見た目を描画するコンポーネントであり、2D Colliderを付けたからといってNavMeshが2D物理演算と連動するわけではありません。 今回の方式では3Dの地面、3D用Collider、3D空間の移動を基本として考えます。
11. うまく動かないとき
- Surfaceが追加できない: AI Navigationパッケージが入っているか、Package Managerの「In Project」で確認する。
- 敵が動かない: SurfaceをBakeしたか、EnemyがNavMesh上にいるか、EnemyChaseのPlayer欄に参照があるかを確認。
- 壁を突き抜ける: Bake後に壁を移動していないか、壁の形状がBake対象か確認し、Bakeし直す。
- 壁を迂回できない: 通路幅とAgent Radius、SurfaceとAgentのAgent Typeの一致、NavMeshが両側で連続しているか確認。
- Spriteが見えない: Visualの回転とSpriteRendererの描画面を確認。
- プレイヤーが壁を抜ける: サンプルのPlayerMoveは衝突未対応。追加の移動制御が必要。
12. NavMeshPlusとの違い
| 比較 | 今回の3Dを2D風に見せる方法 | NavMeshPlus |
|---|---|---|
| Unity公式機能のみ | ○ | ×(外部ライブラリ) |
| 主な移動平面 | XZ | XY |
| 既存2D Tilemapとの相性 | そのままでは使いにくい | 2Dに合わせやすい |
| 得意な用途 | 新規の見下ろし型ゲーム | 既存の2D構成を活用するゲーム |
横スクロールゲームのジャンプや足場の移動は別設計が必要です。目的に合わせて選びましょう。
13. まとめ
3Dの機能だから、3Dにしか使えないとは限りません。 内部はXZ平面の3D、表示はOrthographicで真上から。この切り分けにより、Unity公式NavMesh Agentを2D風ゲームに活用できます。「見せ方」と「動作の仕組み」を分けて考えることが、ゲーム制作の設計力につながります。








ディスカッション
コメント一覧
まだ、コメントがありません