はじめに
Path3DとPathFollow3Dで固定されたパスに沿った移動ができました。しかし、ゲームの多くの場面では「障害物を避けながら目標地点まで自動的に移動してほしい」という要求があります。敵AI、NPC、自動運転など、動的な経路探索が必要な場面で活躍するのがNavigationAgent3Dです。
NavigationAgent3Dを使うと、「ナビゲーションメッシュ」という事前計算された移動可能領域を利用して、複雑な障害物環境でも最適な経路を自動探索できます。敵が部屋の中を蛇行して敵に近づく、NPCが町を自由に歩き回る——こうした知的な動きを簡単に実装できます。
NavigationAgent3Dとは?
NavigationAgent3Dは、3D空間での「経路探索エージェント」です。NavigationRegion3D が定義したナビゲーションメッシュを参照し、現在位置から目標位置までの最適なパスを算出し、次に進むべき位置を教えてくれます。
継承ツリー:
NavigationAgent3D → Node → Object
重要な点として、NavigationAgent3DはNode3Dではなく単なるNodeです。そのため、キャラクターやNPCに子として追加します(親の実際の移動はCharacterBody3Dなどで処理)。
NavigationAgent3Dの主な仕組みは以下の通りです。
- ナビゲーションメッシュ(NavMesh):NavigationRegion3Dで定義された「移動可能な領域」。障害物の周りを自動で迂回する情報を持つ
- 経路探索(A*アルゴリズム):出発点から目標点までの最適なウェイポイント列を算出
- ローカル回避:他のエージェントや動的障害物を避けながら移動
- シグナルベース:目標達成やウェイポイント到達時にシグナルを発火

このノードを使うべき場面
使う場面:
- 敵AI:障害物を避けながらプレイヤーを追跡する敵
- NPC移動:町やダンジョンを歩き回るキャラクター
- 自動運転:指定地点に自動で移動する乗り物やドローン
- 群衆シミュレーション:多数のエージェントが同時に目標地点を目指す
- タワーディフェンス:敵ユニットがマップ上のゴールまで最短経路で移動
使わない場面:
- プレイヤー操作キャラ:プレイヤーの自由な移動にはNavigationAgent3Dは不要(単にCharacterBody3Dで十分)
- ナビゲーションメッシュを用意できない環境:複雑に変形する環境や完全に動的な障害物ばかりの場合、NavMeshの設定・更新が煩雑
主なプロパティと機能
| プロパティ | 型 | 説明 | デフォルト |
|---|---|---|---|
target_position |
Vector3 | 目標位置。この位置までの経路を自動探索 | Vector3.ZERO |
path_desired_distance |
float | パスに沿って生成するウェイポイント間の距離(メートル) | 1.0 |
target_desired_distance |
float | 目標地点と見なす許容距離 | 0.1 |
max_speed |
float | 最大移動速度(m/s)。加速度計算に使用 | 0.0(無制限) |
path_postprocessing |
int(enum) | パス最適化方法(NONE / CORRIDORFUNNEL / EDGECENTROID) | CORRIDORFUNNEL |
主なメソッド:
# 次に進むべき位置を取得
get_next_path_position() -> Vector3
# 目標位置を設定
set_target_position(Vector3 position)
# 経路探索が完了したか確認
is_navigation_finished() -> bool
# 現在のパス(ウェイポイント列)を取得
get_current_navigation_path() -> PackedVector3Array
# 予測される衝突を事前に検知(ローカル回避)
get_avoidance_agent() -> RID
主なシグナル:
# 経路探索が完了し、目標地点に到達した
navigation_finished
# 次のウェイポイントに到達
waypoint_reached(details: Dictionary) # details: { "index": int }
# 目標位置が設定された
target_reached
コード例1:シンプルな敵AI(目標地点を自動追跡)
extends CharacterBody3D
@export var speed = 5.0
@onready var nav_agent = $NavigationAgent3D
func _ready():
nav_agent.target_position = Vector3(10, 0, 10) # 目標位置を設定
func _physics_process(delta):
# 目標位置に到達していなければ移動
if not nav_agent.is_navigation_finished():
var next_pos = nav_agent.get_next_path_position()
var direction = (next_pos - global_position).normalized()
velocity = direction * speed
move_and_slide()
else:
# 到達したら停止
velocity = Vector3.ZERO
print("目標地点に到達しました")
コード例2:プレイヤー追跡敵(ターゲット位置の更新)
extends CharacterBody3D
@export var speed = 4.0
@export var chase_range = 20.0
var player: CharacterBody3D
var is_chasing = false
@onready var nav_agent = $NavigationAgent3D
func _ready():
player = get_tree().get_first_child_in_group("player")
func _physics_process(delta):
if not player:
return
var distance_to_player = global_position.distance_to(player.global_position)
# プレイヤーが範囲内なら追跡開始
if distance_to_player < chase_range:
is_chasing = true
nav_agent.target_position = player.global_position
else:
is_chasing = false
if is_chasing and not nav_agent.is_navigation_finished():
var next_pos = nav_agent.get_next_path_position()
var direction = (next_pos - global_position).normalized()
# プレイヤー方向を向く
look_at(player.global_position, Vector3.UP)
velocity = direction * speed
move_and_slide()
else:
velocity = velocity.lerp(Vector3.ZERO, 0.1) # スムーズに停止
move_and_slide()
コード例3:シグナルを使った目標到達判定
extends CharacterBody3D
@onready var nav_agent = $NavigationAgent3D
var waypoints: PackedVector3Array = []
var current_waypoint_index = 0
func _ready():
# シグナルを接続
nav_agent.waypoint_reached.connect(_on_waypoint_reached)
nav_agent.navigation_finished.connect(_on_navigation_finished)
# 巡回ポイントを設定
waypoints = [
Vector3(0, 0, 0),
Vector3(10, 0, 0),
Vector3(10, 0, 10),
Vector3(0, 0, 10),
]
# 最初のウェイポイントを目指す
nav_agent.target_position = waypoints[current_waypoint_index]
func _physics_process(delta):
if not nav_agent.is_navigation_finished():
var next_pos = nav_agent.get_next_path_position()
var direction = (next_pos - global_position).normalized()
velocity = direction * 5.0
move_and_slide()
else:
velocity = Vector3.ZERO
func _on_waypoint_reached(details: Dictionary):
print("ウェイポイント", details["index"], "に到達")
func _on_navigation_finished():
# 次のウェイポイントに目指す
current_waypoint_index = (current_waypoint_index + 1) % waypoints.size()
nav_agent.target_position = waypoints[current_waypoint_index]
もっと使いこなす:カスタマイズできるパラメータ
まずは基本を動かしてみてから、余裕が出たら試してみてください。
| パラメータ | 目的 | 実装例 |
|---|---|---|
path_desired_distanceを調整 |
ウェイポイント間隔を制御し、移動の滑らかさを調整 | nav_agent.path_desired_distance = 0.5小さいほど細かい経路 |
target_desired_distanceを拡大 |
到達判定の許容距離を広げる(微調整が不要な場合) | nav_agent.target_desired_distance = 1.0大型キャラは距離を広げる |
max_speedを設定 |
AI の最大速度制限(複数敵の速度統制) | nav_agent.max_speed = 5.0 |
path_postprocessingを変更 |
パス最適化の強度を調整 | nav_agent.path_postprocessing = NavigationAgent3D.PATH_POSTPROCESSING_EDGECENTROID直角を避けた移動 |
| 複数敵の同時移動 | 複数のエージェントが群衆シミュレーションを実現 | 複数のCharacterBody3D × NavigationAgent3Dを配置し、各々target_positionを設定 |
応用例:ナビゲーションメッシュの設定方法
# シーンに NavigationRegion3D を追加し、以下の構成にする:
# - NavigationRegion3D
# - 静的障害物(CSGBox3D など)
# - 通路メッシュ(MeshInstance3D など)
# NavigationRegion3D を選択状態で、
# メニュー「Navigation > Bake NavMesh」を実行して NavMesh を生成

まとめ
NavigationAgent3Dは「ナビゲーションメッシュを使った自動経路探索」を実現する、ゲームAI開発の必須ノードです。複雑な障害物環境でも、事前計算されたNavMeshを活用すれば、敵やNPCが知的に移動します。
- 経路探索の自動化:目標位置を設定するだけで、最短経路が自動計算される
- ナビゲーションメッシュが肝:NavigationRegion3Dで事前にNavMeshをベイク(計算)することが重要
- シグナルベースの制御:waypoint_reached や navigation_finished を活用して、イベント駆動な動作を実装
次回は、3Dキャラクターアニメーションの骨格を管理する「Skeleton3D」を解説します。

シリーズ:Godot 4 ノード解説
001〜040:各種ノード | 041~070:個別ノード解説
- 041: CanvasLayer
- 042: ParallaxLayer
- 043: Parallax2D
- 044: Control
- 045: PanelContainer
- 046: TabContainer
- 047: MarginContainer
- 048: AnimationPlayer
- 049: AnimationTree
- 050: Tween
- 051: CPUParticles2D
- 052: GPUParticles2D
- 053: Sprite2D
- 054: CharacterBody2D
- 055: RigidBody2D
- 056: StaticBody2D
- 057: Area2D
- 058: AudioStreamPlayer
- 059: AudioStreamPlayer2D
- 060: AudioStreamPlayer3D
- 061: MultiMeshInstance3D
- 062: MeshInstance3D
- 063: CSGBox3D
- 064: CSGMesh3D
- 065: OmniLight3D
- 066: GridMap
- 067: Path3D
- 068: PathFollow3D
- 069: NavigationAgent3D
- 070: Skeleton3D
この記事はGodot 4.xをもとに執筆しています。


コメント