doc 1 of 6

Pathfinding — getting an agent from A to B when the straight line is a wall

Your enemy chases the player and it looks alive, right up until the player steps behind a wall. Then it presses its face into the brick and stays there. The reflex fix is A*, and roughly half the time A* is the wrong answer — a chase across an open arena needs a direction, not a route, and a route costs you CPU every time the world changes. This shelf teaches you to tell those two cases apart before you write a line of search code, then builds both of the answers Godot actually ships: a grid of cells that knows which ones are solid, and a mesh of walkable space that never thinks in cells at all. It finishes with the part nobody writes down — how often to recompute, how to stop a path from looking like graph paper, and what an enemy should do when there is no path to you at all.

What this shelf teaches#

PartYou buildThe idea
01A CharacterBody2D chasing directly, then steering around a pillar with two raycasts.Steering asks only "which way is the target" — no memory, no lookahead.
02An AStarGrid2D from a TileMapLayer, routing an agent around part 01's wall.A grid is one boolean per cell, set in an API-enforced order.
03The same level walkable via a baked NavigationRegion2D, queried directly with no agent node.A grid pays for area; a mesh pays for shape complexity.
04A CharacterBody2D driven by NavigationAgent2D, arriving cleanly and sliding past a second agent.The agent node is a path cache, not a mover of your body.
05A staggered repath timer, a string-pulled path, a droppable obstacle, a defined no-path behaviour.The algorithm was never the expensive part — cadence and edge cases are.

Part 01 ends with a written test — four questions about your level that tell you whether to stop there. Steering can never choose a direction that temporarily increases distance to the target, and a U-shaped wall proves it. Part 02 draws its path on screen so you can see what the search produced; break the cell-marking order and the API refuses loudly, hundreds of times, in an output panel most people never check while the agent keeps moving. Part 03 draws its mesh path beside part 02's grid path for comparison — a 4000-by-4000 open field is a million cells or about four polygons, and the navigation server updates on its own schedule, not yours. Part 04's agent stops dead on arrival instead of vibrating, and every symptom you debug afterward comes from expecting the node to move your body, which it never does. Part 05's repath timer includes a moved-far-enough test, and its string-pulling strips waypoints that changed nothing — cadence, smoothing, dynamic geometry, and the no-path case are what separate an enemy that reads as thinking from one that reads as broken.

Where reasonable people differ#

Four forks run through this shelf. None has a correct side. Each has a question that decides it for your project.

Steering or search. Direct pursuit with whiskers is close to free, needs no map data, and survives in shipped games far longer than tutorials admit. A search costs you a grid or mesh to maintain, solid flags to keep in sync, a repath policy, and a plan for failure. Deciding question: does concave geometry ever sit between the agent and the target — a U, a room with one door, a wall the agent must first move away from the player to get around? One yes buys the whole apparatus. No yeses and the search is maintenance you pay for nothing.

Grid or mesh. A grid quantises space into cells and its cost scales with the area of your level. A mesh describes walkable space as convex polygons and its cost scales with how complicated the shapes are. Deciding question: does your game already talk about cells? Tile-based building, per-tile terrain cost, anything where "which tile is that" is a question your gameplay code asks — the grid is already there and you should use it. Free-form, angled, hand-authored, or large geometry wants a mesh.

NavigationAgent2D or one-shot queries. The agent node caches a path, tracks which waypoint you are on, and can run avoidance. It also brings a per-frame contract you have to honour exactly. A one-shot NavigationServer2D.map_get_path call is a function that returns an array and then forgets you exist. Deciding question: does the target keep moving? A click-to-move cursor, a patrol route computed once at level start, and an off-screen agent that recalculates rarely are all cleaner as one-shot calls. The agent node earns its complexity when the destination will not hold still.

Repath on a clock or repath on an event. A timer is predictable, cheap to stagger across many agents, and always slightly stale. Invalidating on an event — the target crossed a threshold, a door opened, a crate landed — is exact and needs every one of those events to be findable and wired. Deciding question: which changes more often, your target or your world? Chasing a player, a clock plus a moved-far-enough test wins. Long routes through a world that changes rarely, invalidation wins and costs less.

Prerequisites#

  • Typed GDScript, including typed function signatures and return types. Start at /library/programming/01-typed-gdscript if the annotations in these parts look unfamiliar.
  • CharacterBody2D, velocity, and move_and_slide inside _physics_process. You will write all the movement yourself in every part of this shelf — nothing here moves a body for you.
  • Enough TileMapLayer to place tiles and know what a used rect is. Part 02 reads walls out of one.
  • Signals connected in code, since avoidance in part 04 arrives through velocity_computed rather than a return value.
  • Helpful but not required: a state machine, so that "chasing" is a state rather than a boolean. Pathfinding is what a chase state does; it is not the decision to chase. See /systems/state-machine/01-when-you-need-one.

Where this shows up in the projects#

The farming curriculum at /farming_game/ is the case this shelf was written for: villagers and animals crossing a tile world, on a grid your gameplay code already thinks in, with fences and buildings the player moves around at runtime. Parts 02 and 05 map onto it directly.

The platformer at /precision_platformer/tutorial/00-overview is the honest counterexample. Its enemies move along authored paths under gravity, and dropping a navigation mesh into it would add a system that answers a question the design never asks. Reading part 01 and then deciding to stop is a complete and correct outcome.


Next: Part 01 — the chase that does not need a path. Read it before you install anything, including if you are certain you need A* — the test at the end of it is short, and the enemy you build there is the one you keep if the test comes back no.