thedivergentai/godot-ai-navigation
AI movement decision router for chase, patrol, crowd, and bake choices on top of NavigationAgent/Server. Use when deciding node agent vs RID server, bake vs obstacle, layer masks, or retarget policy — not for engine navmesh recipes. Keywords: AI navigation, chase retarget, patrol, crowd RVO, bake vs obstacle, NavigationAgent decision tree.
npx skills add https://github.com/thedivergentai/GD-Agentic-Skills --skill godot-ai-navigation
This skill owns AI movement decisions. Authoritative NavigationServer scripts live in godot-navigation-pathfinding — this package intentionally has no scripts/ (no dead local links).
> MANDATORY: Before implementing path/bake/avoidance code, open godot-navigation-pathfinding and read the linked script(s) below. Do NOT Load beginner chase/patrol tutorials from memory — follow these trees, then only the pathfinding scripts you selected.
| Signal | Choice | Pathfinding script (MANDATORY read) |
| :--- | :--- | :--- |
| 2D top-down / side-scroller, < ~50 agents, editor-tweakable | NavigationAgent2D on CharacterBody2D | smart_navigation_agent.gd |
| 3D floor/slope nav, < ~50 agents, designer-placed regions | NavigationAgent3D on CharacterBody3D | Same script (3D branch); pair with godot-physics-3d for body collision |
| Hundreds–thousands of simple movers (2D or 3D) | RID agents on NavigationServer | server_navigation_setup.gd + low_level_avoidance.gd |
| Agents stuck / jittering | Stuck recovery before retarget spam | agent_stuck_detection.gd |
| Signal | Choice | Pathfinding script (MANDATORY read) |
| :--- | :--- | :--- |
| Walkable geometry changed (proc gen, doors) | Async parse + bake | async_dynamic_baking.gd |
| Moving platform / shifting region | Dynamic region manager | dynamic_nav_manager.gd |
| Projectile / rolling hazard pushing agents | RVO obstacle (no full rebake) | moving_obstacle_server.gd |
| Prefer roads over mud/water | Region enter/travel costs | terrain_cost_manager.gd |
| Signal | Choice | Pathfinding script (MANDATORY read) |
| :--- | :--- | :--- |
| Walk / fly / swim (or faction) filters | Navigation layers bitmasks | layer_mask_navigation.gd |
| Jump / teleport / elevator edges | NavigationLink traversal | nav_link_traversal.gd |
| Formation / anti-clump crowds | Leader-relative offsets | group_avoidance_formations.gd |
| Hot-path query allocs | Reuse query parameter/result objects | memory_optimized_queries.gd |
Do NOT Load scripts outside the chosen row (e.g. skip RID/server scripts for a single designer-tuned agent; skip async bake when only RVO obstacles move).
target_position every physics frame.is_navigation_finished() and is_target_reachable(); on unreachable, pick next or repath.Patrol state handoff (call site): in the patrol state's _physics_process, when the agent finishes a waypoint, call retarget_if_needed(next_waypoint) — do not set target_position directly from the state machine root.
# PatrolState.gd — state machine owns transitions; this skill owns retarget policy
func _physics_process(_delta: float) -> void:
if nav_agent.is_navigation_finished() and nav_agent.is_target_reachable():
_ai_nav.retarget_if_needed(_waypoints[_index])
_index = (_index + 1) % _waypoints.size()
# Threshold retarget — AI policy, not per-frame path spam
const RETARGET_DIST := 1.5
var _last_target: Vector3
func retarget_if_needed(desired: Vector3) -> void:
if desired.distance_to(_last_target) < RETARGET_DIST:
return
nav_agent.target_position = desired
_last_target = desired
target_position before awaiting physics frame — MUST call_deferred() then await get_tree().physics_frame.bake_from_source_geometry_data_async via pathfinding async_dynamic_baking.gd.is_target_reachable() / stuck recovery — Unreachable or stalled agents need policy (agent_stuck_detection.gd).avoidance_enabled — Agents pass through each other.get_path() every frame — Reuse path query objects (memory_optimized_queries.gd).If the sibling skill is unavailable, use this minimal stuck-recovery checklist — do not paste full bake/RID tutorials from memory:
target_position with call_deferred + await get_tree().physics_frame.!nav_agent.is_target_reachable() or velocity ≈ 0 for N frames, skip waypoint or call get_next_path_position() recovery.radius > 0 when avoidance_enabled._ready(). call_deferred + await physics_frame prevents first-path failure.target_position rebakes paths and spikes CPU. Timer (~0.2 s) or distance threshold only.is_target_reachable() + skip/repath policy.| Topic | Reference / script |
|-------|-------------------|
| Chase / patrol / crowd AI recipes | ai-movement-recipes.md |
> Progressive disclosure: open Official Documentation links only when researching a specific API; load Related Skills when routing to a peer domain — do not preload the whole lattice.
scripts/.Take thedivergentai/godot-ai-navigation from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.