thedivergentai/godot-navigation-pathfinding
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 skills add https://github.com/thedivergentai/GD-Agentic-Skills --skill godot-navigation-pathfinding
NavigationServer pathfinding, async bake, RVO avoidance, and stuck recovery — not editor intro recipes.
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.> MANDATORY for the chosen path. Do NOT Load editor-intro / Official Docs bootstrap recipes from this skill body (use Reference links when you need first-time region setup).
| Need | Script |
|------|--------|
| Runtime / procedural bake without hitch | MANDATORY async_dynamic_baking.gd |
| Agent stuck / jitter recovery | MANDATORY agent_stuck_detection.gd |
| High-count RVO without nodes | MANDATORY low_level_avoidance.gd |
| Moving platforms / dynamic regions | dynamic_nav_manager.gd |
| RID-only maps/regions | server_navigation_setup.gd |
| Reused path query objects | memory_optimized_queries.gd |
| Terrain enter/travel costs | terrain_cost_manager.gd |
| Projectiles as RVO obstacles | moving_obstacle_server.gd |
| Links (jump/teleport/elevator) | nav_link_traversal.gd |
| Walk / fly / swim layers | layer_mask_navigation.gd |
| Crowd formation offsets | group_avoidance_formations.gd |
| Server RVO crowd agent (node-less) | crowd_agent_3d.gd |
| Dynamic navmesh carve (impact holes) | nav_mesh_carver_3d.gd |
| Bake-time benchmark | navmesh_profiler.gd |
| Smart agent wrapper | smart_navigation_agent.gd |
Do not assign target_position every physics frame. Retarget on a timer (~0.2s) or when the chased body moves beyond a distance threshold:
# Threshold retarget — not per-frame path spam
const RETARGET_DIST := 1.5
var _last_target: Vector3
func _physics_process(_delta: float) -> void:
var desired := prey.global_position
if desired.distance_to(_last_target) >= RETARGET_DIST:
nav_agent.target_position = desired
_last_target = desired
if nav_agent.is_navigation_finished():
return
var next := nav_agent.get_next_path_position()
velocity = (next - global_position).normalized() * speed
move_and_slide()
bake_from_source_geometry_data_async — parse on main, bake off-thread.
Distance-over-time stall detection and recovery.
Server-side RVO agents + avoidance callbacks.
Runtime navmesh updates for moving platforms.
Node-less maps/regions via NavigationServer RIDs.
Reuse path query parameter/result objects.
enter_cost / travel_cost for preferred routes.
Dynamic RVO obstacles without full rebake.
NavigationLink jump/teleport/elevator handling.
Multi-domain navigation layers (walk/fly/swim).
Leader-relative offsets to reduce clumping.
Production NavigationAgent wrapper patterns.
> Progressive disclosure: open Official Documentation links only when researching a specific API;
> load Related Skills when routing work to a peer domain — do not preload the whole lattice.
Take thedivergentai/godot-navigation-pathfinding 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.