Introduction
はじめに
Godot 4 has a robust navigation system built on NavigationServer2D/3D, NavigationRegion nodes, and NavigationAgent nodes. It's a significant improvement over Godot 3's system — more flexible, more performant, and much easier to configure for complex scenarios like dynamic obstacles and multiple agent types.
Godot 4にはNavigationServer2D/3D、NavigationRegionノード、NavigationAgentノードを基盤とした堅牢なナビゲーションシステムがあります。Godot 3のシステムから大幅に改善され、動的障害物や複数エージェントタイプなどの複雑なシナリオの設定が、より柔軟で高性能かつ簡単になっています。
Quick overview: NavigationRegion defines where agents can walk. NavigationAgent handles pathfinding for individual entities. NavigationServer manages everything behind the scenes.
概要: NavigationRegionはエージェントが歩ける場所を定義します。NavigationAgentは個々のエンティティのパスファインディングを処理します。NavigationServerがバックグラウンドですべてを管理します。
Core Concepts
基本概念
- NavigationRegion2D / NavigationRegion3D — Defines a walkable area using a NavigationPolygon (2D) or NavigationMesh (3D). You can have multiple regions; the server merges them automatically. NavigationRegion2D / NavigationRegion3D — NavigationPolygon(2D)またはNavigationMesh(3D)を使って歩行可能エリアを定義します。複数のリージョンを持てます。サーバーが自動的に結合します。
- NavigationAgent2D / NavigationAgent3D — Attach to a CharacterBody to handle pathfinding. Computes the next path position, handles avoidance, and emits signals when navigation finishes. NavigationAgent2D / NavigationAgent3D — CharacterBodyにアタッチしてパスファインディングを処理します。次のパス位置を計算し、回避を処理し、ナビゲーション完了時にシグナルを発信します。
- NavigationServer2D / NavigationServer3D — Singleton that manages all navigation data. You rarely interact with it directly, but it handles map updates, path queries, and region connections. NavigationServer2D / NavigationServer3D — すべてのナビゲーションデータを管理するシングルトン。直接操作することは稀ですが、マップ更新、パスクエリ、リージョン接続を処理します。
2D Navigation Setup
2Dナビゲーションのセットアップ
Step 1: Add NavigationRegion2D
ステップ1:NavigationRegion2Dの追加
- Add a NavigationRegion2D node to your scene. シーンにNavigationRegion2Dノードを追加します。
- In the Inspector, create a new NavigationPolygon resource. インスペクターで新しいNavigationPolygonリソースを作成します。
- Draw the walkable polygon in the 2D editor. The polygon defines where agents can walk. 2Dエディタで歩行可能なポリゴンを描画します。ポリゴンはエージェントが歩ける場所を定義します。
TileMap integration: NavigationPolygon can be baked from TileMap data. If your tiles have navigation polygons defined in the TileSet, just add a NavigationRegion2D and bake — it will automatically generate the walkable area from your tile layout.
TileMap連携: NavigationPolygonはTileMapデータからベイクできます。タイルにTileSetでナビゲーションポリゴンが定義されていれば、NavigationRegion2Dを追加してベイクするだけで、タイルレイアウトから自動的に歩行可能エリアが生成されます。
Adding a NavigationAgent2D
NavigationAgent2Dの追加
Add a NavigationAgent2D as a child of your CharacterBody2D. Here's a complete movement script:
CharacterBody2Dの子としてNavigationAgent2Dを追加します。完全な移動スクリプトは以下の通り:
extends CharacterBody2D
@export var speed: float = 200.0
@onready var nav_agent: NavigationAgent2D = $NavigationAgent2D
func _ready() -> void:
# Wait for the navigation map to be ready
await get_tree().physics_frame
nav_agent.path_desired_distance = 4.0
nav_agent.target_desired_distance = 4.0
func set_target(target_pos: Vector2) -> void:
nav_agent.target_position = target_pos
func _physics_process(delta: float) -> void:
if nav_agent.is_navigation_finished():
return
var next_pos := nav_agent.get_next_path_position()
var direction := global_position.direction_to(next_pos)
velocity = direction * speed
move_and_slide()
Important: The NavigationServer needs one physics frame to synchronize. Always await get_tree().physics_frame before setting the first target position in _ready(), or the agent may not find a valid path.
重要: NavigationServerは同期に1物理フレームが必要です。_ready()で最初のターゲット位置を設定する前に、必ずawait get_tree().physics_frameを実行してください。そうしないとエージェントが有効なパスを見つけられない場合があります。
Key NavigationAgent2D Properties
NavigationAgent2Dの主要プロパティ
-
target_position— Where the agent wants to gotarget_position— エージェントの目的地 -
path_desired_distance— How close the agent needs to be to each path point to advance to the next onepath_desired_distance— 次のパスポイントに進むために必要な各パスポイントへの近接距離 -
target_desired_distance— How close the agent needs to be to the target to consider navigation finishedtarget_desired_distance— ナビゲーション完了と判定するためのターゲットへの近接距離 -
max_speed— Used for avoidance calculations (does not limit your movement code)max_speed— 回避計算に使用(移動コードの制限はしない)
3D Navigation
3Dナビゲーション
The 3D navigation system works identically to 2D, just with different node types:
3Dナビゲーションシステムは2Dと同様に動作します。ノードタイプが異なるだけです:
NavigationRegion3D+NavigationMeshNavigationAgent3DNavigationServer3D
extends CharacterBody3D
@export var speed: float = 5.0
@onready var nav_agent: NavigationAgent3D = $NavigationAgent3D
func _ready() -> void:
await get_tree().physics_frame
nav_agent.path_desired_distance = 0.5
nav_agent.target_desired_distance = 0.5
func set_target(target_pos: Vector3) -> void:
nav_agent.target_position = target_pos
func _physics_process(delta: float) -> void:
if nav_agent.is_navigation_finished():
return
var next_pos := nav_agent.get_next_path_position()
var direction := global_position.direction_to(next_pos)
velocity = direction * speed
velocity.y -= 9.8 * delta # Apply gravity
move_and_slide()
Baking Navigation Meshes
ナビゲーションメッシュのベイク
For 3D, you typically bake the navigation mesh from your level geometry rather than drawing it by hand.
3Dでは通常、手動で描画するのではなく、レベルジオメトリからナビゲーションメッシュをベイクします。
Baking Configuration
ベイク設定
Key properties in the NavigationMesh resource:
NavigationMeshリソースの主要プロパティ:
- Agent Radius — How far agents stay from walls. Larger values create more conservative paths. Agent Radius — エージェントが壁からどれだけ離れるか。値が大きいほど保守的なパスになります。
- Agent Height — Minimum ceiling height for walkable areas. Agent Height — 歩行可能エリアの最小天井高。
- Agent Max Climb — Maximum step height agents can walk up (e.g., stairs). Agent Max Climb — エージェントが歩いて登れる最大段差(例:階段)。
- Agent Max Slope — Maximum walkable slope angle in degrees. Agent Max Slope — 歩行可能な最大傾斜角度(度)。
# Bake navigation mesh at runtime
var nav_region: NavigationRegion3D = $NavigationRegion3D
nav_region.bake_navigation_mesh()
# Wait for baking to complete
await nav_region.bake_finished
print("Navigation mesh baked!")
Navigation Layers
ナビゲーションレイヤー
Navigation layers let you separate walkable areas for different agent types. For example, ground units and flying units can have different navigation meshes.
ナビゲーションレイヤーにより、エージェントタイプごとに歩行可能エリアを分離できます。例えば、地上ユニットと飛行ユニットに異なるナビゲーションメッシュを設定できます。
# Set navigation layers on the agent
nav_agent.set_navigation_layer_value(1, true) # Ground layer
nav_agent.set_navigation_layer_value(2, false) # Not flying layer
# Set navigation layers on the region
nav_region.set_navigation_layer_value(1, true) # This region is for ground
nav_region.set_navigation_layer_value(2, false) # Not for flying
A typical layer setup:
一般的なレイヤー設定:
- Layer 1 — Ground units (soldiers, vehicles) Layer 1 — 地上ユニット(兵士、車両)
- Layer 2 — Flying units (drones, birds) Layer 2 — 飛行ユニット(ドローン、鳥)
- Layer 3 — Large units (only wide corridors) Layer 3 — 大型ユニット(広い通路のみ)
Avoidance
回避(Avoidance)
NavigationAgent has built-in local avoidance to prevent agents from overlapping. When avoidance is enabled, the agent computes a safe velocity that steers away from other agents.
NavigationAgentにはエージェントの重なりを防ぐためのローカル回避機能が組み込まれています。回避が有効な場合、エージェントは他のエージェントを避ける安全な速度を計算します。
extends CharacterBody2D
@export var speed: float = 200.0
@onready var nav_agent: NavigationAgent2D = $NavigationAgent2D
func _ready() -> void:
await get_tree().physics_frame
nav_agent.avoidance_enabled = true
nav_agent.radius = 20.0
nav_agent.max_speed = speed
nav_agent.velocity_computed.connect(_on_velocity_computed)
func set_target(target_pos: Vector2) -> void:
nav_agent.target_position = target_pos
func _physics_process(delta: float) -> void:
if nav_agent.is_navigation_finished():
return
var next_pos := nav_agent.get_next_path_position()
var direction := global_position.direction_to(next_pos)
# Set the desired velocity — the agent will compute a safe one
nav_agent.velocity = direction * speed
func _on_velocity_computed(safe_velocity: Vector2) -> void:
velocity = safe_velocity
move_and_slide()
How it works: Instead of using the velocity directly, you set nav_agent.velocity to your desired velocity. The agent then computes a safe_velocity via the velocity_computed signal that avoids nearby agents. You apply this safe velocity in the callback.
仕組み: velocityを直接使う代わりに、nav_agent.velocityに希望の速度を設定します。エージェントがvelocity_computedシグナルを通じて、近くのエージェントを避けるsafe_velocityを計算します。コールバックでこの安全な速度を適用します。
Dynamic Navigation
動的ナビゲーション
You can modify the navigation mesh at runtime to handle doors, destructible walls, or changing terrain:
ドア、破壊可能な壁、変化する地形に対応するため、ランタイムでナビゲーションメッシュを変更できます:
# Enable/disable a navigation region (e.g., open/close a door)
var door_region: NavigationRegion2D = $DoorNavigationRegion
door_region.enabled = false # Block this path
door_region.enabled = true # Open this path
# Add a navigation obstacle (blocks agent paths)
var obstacle := NavigationObstacle2D.new()
obstacle.radius = 30.0
add_child(obstacle)
# Re-bake after level changes (3D)
nav_region.bake_navigation_mesh()
await nav_region.bake_finished
Performance note: Baking a 3D navigation mesh at runtime is expensive. For dynamic obstacles in 3D, prefer using NavigationObstacle3D instead of re-baking. For 2D, you can toggle NavigationRegion2D.enabled cheaply.
パフォーマンス注意: 3Dナビゲーションメッシュのランタイムベイクはコストが高いです。3Dの動的障害物には再ベイクの代わりにNavigationObstacle3Dを使用してください。2DではNavigationRegion2D.enabledの切り替えは低コストです。
Common Patterns
よくあるパターン
Enemy AI Following Player
プレイヤーを追跡する敵AI
extends CharacterBody2D
@export var speed: float = 150.0
@export var chase_range: float = 300.0
@onready var nav_agent: NavigationAgent2D = $NavigationAgent2D
var player: Node2D
func _ready() -> void:
await get_tree().physics_frame
player = get_tree().get_first_node_in_group("player")
func _physics_process(delta: float) -> void:
if not player:
return
var distance := global_position.distance_to(player.global_position)
if distance > chase_range:
return # Too far, don't chase
# Update target every frame (or throttle to every N frames)
nav_agent.target_position = player.global_position
if nav_agent.is_navigation_finished():
return
var next_pos := nav_agent.get_next_path_position()
var direction := global_position.direction_to(next_pos)
velocity = direction * speed
move_and_slide()
NPC Patrol Routes
NPCの巡回ルート
extends CharacterBody2D
@export var speed: float = 100.0
@export var patrol_points: Array[Vector2] = []
@onready var nav_agent: NavigationAgent2D = $NavigationAgent2D
var current_patrol_index: int = 0
func _ready() -> void:
await get_tree().physics_frame
if patrol_points.size() > 0:
nav_agent.target_position = patrol_points[0]
func _physics_process(delta: float) -> void:
if patrol_points.size() == 0:
return
if nav_agent.is_navigation_finished():
# Move to next patrol point
current_patrol_index = (current_patrol_index + 1) % patrol_points.size()
nav_agent.target_position = patrol_points[current_patrol_index]
return
var next_pos := nav_agent.get_next_path_position()
var direction := global_position.direction_to(next_pos)
velocity = direction * speed
move_and_slide()
Click-to-Move (Top-Down)
クリック移動(トップダウン)
extends CharacterBody2D
@export var speed: float = 200.0
@onready var nav_agent: NavigationAgent2D = $NavigationAgent2D
func _ready() -> void:
await get_tree().physics_frame
func _unhandled_input(event: InputEvent) -> void:
if event is InputEventMouseButton and event.pressed:
nav_agent.target_position = get_global_mouse_position()
func _physics_process(delta: float) -> void:
if nav_agent.is_navigation_finished():
return
var next_pos := nav_agent.get_next_path_position()
var direction := global_position.direction_to(next_pos)
velocity = direction * speed
move_and_slide()
Godot 3 to Godot 4 Changes
Godot 3からGodot 4への変更点
| Godot 3 | Godot 4 |
|---|---|
Navigation2D node |
Removed. Use NavigationRegion2D + NavigationAgent2D廃止。NavigationRegion2D + NavigationAgent2Dを使用 |
Navigation.get_simple_path() |
NavigationServer2D.map_get_path() |
| Manual path following手動パス追跡 | NavigationAgent.get_next_path_position() handles itNavigationAgent.get_next_path_position()が処理 |
| No built-in avoidance回避機能なし | NavigationAgent.avoidance_enabledNavigationAgent.avoidance_enabled |
| No navigation layersナビゲーションレイヤーなし | 32 navigation layers per mapマップごとに32ナビゲーションレイヤー |
| No obstacles障害物なし | NavigationObstacle2D/3D |