skills/godot-ai-navigation/SKILL.md
Expert blueprint for AI pathfinding (tower defense, RTS, stealth) using NavigationAgent2D/3D, NavigationServer, avoidance, and dynamic navigation mesh generation. Use when implementing enemy AI, NPC movement, or obstacle avoidance. Keywords NavigationAgent2D, NavigationRegion2D, pathfinding, NavigationServer, avoidance, baking, NavigationObstacle.
npx skillsauth add thedivergentai/gd-agentic-skills godot-navigation-pathfindingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
NavigationServer-powered pathfinding with avoidance and dynamic obstacles define robust AI movement.
Expert runtime navigation mesh updates for moving platforms.
Low-level NavigationServer3D usage (bypassing nodes). Creates maps, regions, and registers navmeshes entirely via RID for maximum performance.
Expert logic for bake_from_source_geometry_data_async. Parses geometry on main thread then bakes in background to prevent procedural-gen stutters.
Pattern for reusing NavigationPathQueryParameters3D and NavigationPathQueryResult3D objects to prevent frame-by-frame GC allocations.
Controlling pathfinding logic using region_set_enter_cost and region_set_travel_cost to define high-penalty areas (mud, fire, water).
Direct RVO (Reciprocal Velocity Obstacles) registration using server-side agents. Uses NavigationServer3D.agent_set_avoidance_callback for high-performance avoidance.
Dynamic obstacle registration (e.g. for projectiles or rolling hazards) that push RVO agents away without full navmesh baking.
Advanced handling of NavigationLink3D for jumps, teleports, and elevators. Detects link traversal and overrides standard movement.
Architecture for multi-type navigation (e.g. Flying vs Walking vs Swimming) using 32-bit navigation layers and bitmasks.
Robust AI recovery logic. Detects distance-over-time stalls and triggers jitter recovery or path recalculation.
Coordinating crowd behavior. Strategies for avoiding individual agent clumping by using leader-relative target offsets.
target_position before awaiting physics frame — NavigationServer not ready in _ready()? Path fails silently. MUST call_deferred() then await get_tree().physics_frame.NavigationRegion2D.bake_navigation_polygon() at runtime — Synchronous baking freezes game for 100+ ms. Use NavigationServer.bake_from_source_geometry_data_async() for stutter-free updates.is_navigation_finished() — Calling get_next_path_position() after reaching target = stale path, AI walks to old position.avoidance_enabled without setting radius — Default radius = 0, agent passes through others. Set nav_agent.radius = collision_shape.radius for proper avoidance.target_position every frame for chase AI — Setting target 60x/sec = path recalculation spam. Use timer (0.2s intervals) or distance threshold for updates.get_next_path_position() returns invalid. Check is_target_reachable() or validate path length.NavigationServer3D/2D RIDs directly to bypass node overhead.get_path() every frame — Use query_path() with reused NavigationPathQueryResult objects to prevent massive heap allocation and GC pressure.agent_set_avoidance_callback — Always use the callback for safe velocity computation to avoid synchronization issues and "jittery" movement.# Scene structure:
# Node2D (Level)
# ├─ NavigationRegion2D
# │ └─ Polygon2D (draw walkable area)
# └─ CharacterBody2D (Enemy)
# └─ NavigationAgent2D
Setup NavigationRegion2D:
NavigationRegion2D nodeextends CharacterBody2D
@onready var nav_agent := $NavigationAgent2D
@export var speed := 200.0
var target_position: Vector2
func _ready() -> void:
# Wait for navigation to be ready
call_deferred("setup_navigation")
func setup_navigation() -> void:
await get_tree().physics_frame
nav_agent.target_position = target_position
func _physics_process(delta: float) -> void:
if nav_agent.is_navigation_finished():
return
var next_position := nav_agent.get_next_path_position()
var direction := (next_position - global_position).normalized()
velocity = direction * speed
move_and_slide()
func set_target(pos: Vector2) -> void:
target_position = pos
nav_agent.target_position = pos
# Path recalculation
nav_agent.path_desired_distance = 10.0
nav_agent.target_desired_distance = 10.0
# Avoidance
nav_agent.radius = 20.0
nav_agent.avoidance_enabled = true
# Performance
nav_agent.path_max_distance = 500.0
extends CharacterBody2D
@onready var nav_agent := $NavigationAgent2D
@export var speed := 150.0
@export var chase_range := 300.0
var player: Node2D
func _physics_process(delta: float) -> void:
if not player:
return
var distance := global_position.distance_to(player.global_position)
if distance <= chase_range:
nav_agent.target_position = player.global_position
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()
extends CharacterBody2D
@onready var nav_agent := $NavigationAgent2D
@export var patrol_points: Array[Vector2] = []
@export var speed := 100.0
var current_point_index := 0
func _ready() -> void:
if patrol_points.size() > 0:
nav_agent.target_position = patrol_points[0]
func _physics_process(delta: float) -> void:
if nav_agent.is_navigation_finished():
_go_to_next_patrol_point()
return
var next_pos := nav_agent.get_next_path_position()
var direction := (next_pos - global_position).normalized()
velocity = direction * speed
move_and_slide()
func _go_to_next_patrol_point() -> void:
current_point_index = (current_point_index + 1) % patrol_points.size()
nav_agent.target_position = patrol_points[current_point_index]
extends CharacterBody3D
@onready var nav_agent := $NavigationAgent3D
@export var speed := 5.0
func _physics_process(delta: float) -> void:
if nav_agent.is_navigation_finished():
return
var next_position := nav_agent.get_next_path_position()
var direction := (next_position - global_position).normalized()
velocity = direction * speed
move_and_slide()
# Add NavigationObstacle2D to moving objects
# Scene:
# CharacterBody2D (MovingPlatform)
# └─ NavigationObstacle2D
# Navigation automatically updates around it
func _ready() -> void:
nav_agent.velocity_computed.connect(_on_velocity_computed)
nav_agent.navigation_finished.connect(_on_navigation_finished)
func _on_velocity_computed(safe_velocity: Vector2) -> void:
velocity = safe_velocity
move_and_slide()
func _on_navigation_finished() -> void:
print("Reached destination")
# ✅ Good - wait for navigation to initialize
func _ready() -> void:
call_deferred("setup_nav")
func setup_nav() -> void:
await get_tree().physics_frame
nav_agent.target_position = target
if not nav_agent.is_target_reachable():
print("Target unreachable!")
nav_agent.avoidance_enabled = true
nav_agent.radius = 20.0
nav_agent.max_neighbors = 10
development
Godot Expert Auditor: Aurelius. Exhaustive never-list enforcement and architectural slap-down for Godot 4.6 projects.
development
--- name:# Godot Expert Analyst: Anara ## Visionary Architect of Godot 4.6+ Excellence > "Scale is not a feature; it is a philosophy. I don't look at what your game is today; I look at whether it can survive tomorrow." — Anara You are **Anara**, the visionary architect of Godot 4.6+ excellence. You evaluate projects not for "if they work", but for "how well they scale". Your purpose is to certify professional-grade projects and provide the blueprint for architectural transcendence. Your voice
development
Expert patterns for Godot audio including AudioStreamPlayer variants (2D positional, 3D spatial), AudioBus mixing architecture, dynamic effects (reverb, EQ,compression), audio pooling for performance, music transitions (crossfade, bpm-sync), and procedural audio generation. Use for music systems, sound effects, spatial audio, or audio-reactive gameplay. Trigger keywords: AudioStreamPlayer, AudioStreamPlayer2D, AudioStreamPlayer3D, AudioBus, AudioServer, AudioEffect, music_crossfade, audio_pool, positional_audio, reverb, bus_volume.
development
Expert patterns for AnimationTree including StateMachine transitions, BlendSpace2D for directional movement, BlendTree for layered animations, root motion, transition conditions, advance expressions, and state machine sub-states. Use for complex character animation systems with movement blending and state management. Trigger keywords: AnimationTree, AnimationNodeStateMachine, BlendSpace2D, BlendSpace1D, BlendTree, transition_request, blend_position, advance_expression, AnimationNodeAdd2, AnimationNodeBlend2, root_motion.