Guide

Game GOAP explained

Harbor Outpost's colonists were supposed to feel autonomous — chop wood when stockpiles ran low, cook when hungry, sleep when exhausted. The first build used a rigid finite state machine with 14 hard-coded transitions. Players noticed NPCs standing idle beside full lumber yards while the cook fire went cold: the FSM could not chain “walk to tree → chop → haul → cook” unless every sequence was pre-authored. Switching to goal-oriented action planning (GOAP) let each colonist search for a short action chain that transforms the current world state into a goal state (HasCookedMeal=true) using reusable actions with preconditions and effects. Idle time dropped 61%, bug reports about “dumb settlers” fell 80%, and playtesters started sharing emergent stories the team never scripted. GOAP is a planning paradigm: designers define symbolic facts, actions that read and write those facts, and goals as desired fact sets; a planner (usually A* over actions) finds a valid sequence at runtime. This guide covers world state representation, action authoring, the planning loop, replanning triggers, a Harbor Outpost worked example, a GOAP vs behavior tree decision table, pitfalls, and a production checklist.

What GOAP is (and what it is not)

Goal-oriented action planning treats NPC behavior as a search problem. The agent knows:

  • Current world state — a set of symbolic facts (key-value pairs or predicates) describing what is true right now: At(TreePatch), HasAxe=true, Hunger=0.8.
  • Available actions — reusable operators, each with preconditions (facts that must hold to start) and effects (facts that change when the action completes): ChopWood requires At(Tree) and HasAxe; on success it adds HasLog=true and removes TreeChopped.
  • A goal state — facts the planner must achieve: Hunger<0.2 or Stockpile(Wood)>=10.

The planner searches backward or forward through action space — classically A* where edge cost is action cost (time, risk, stamina) — until it finds a chain whose combined effects satisfy the goal. The NPC then executes actions in order, replanning when the world changes.

GOAP is not machine learning, pathfinding, or animation. It does not replace navmesh movement; actions call into locomotion and animation systems when they run. It is also not a silver bullet for combat reflexes — shooters still use behavior trees for frame-tight dodge-and-shoot loops. GOAP shines in simulation, survival, stealth, and RPG sandbox loops where multi-step plans create believable autonomy.

World state: symbols, not pixels

GOAP operates on symbolic state, not raw geometry. Facts should be cheap to read and stable for the duration of one plan:

  • Boolean flags: DoorOpen(Kitchen), HasWeapon.
  • Enumerations: Location=Forest, Job=Idle.
  • Numeric thresholds: Hunger, Energy, WoodStockpile (often bucketed to reduce branching).

Bridging perception to symbols

A perception layer (sensors, trigger volumes, inventory queries) updates facts each tick or on events. Keep this layer separate from actions: the planner assumes facts are true when preconditions match. If perception lags — the colonist thinks a tree exists but it was already chopped — execution fails and triggers replanning.

State explosion

Every new fact multiplies the search space. Production GOAP uses fact pruning: only symbols relevant to the current goal set enter the planner; distant world events stay in a blackboard the planner ignores until a goal references them. Harbor Outpost tracks 40 facts per colonist but only 12 participate in any single plan.

Authoring actions

Each action is a data record plus an execution hook:

  1. Name and costCookMeal cost 3 (seconds or abstract effort); cheaper paths win when multiple plans exist.
  2. Preconditions — all must be true: At(Kitchen), HasLog=true, FireLit=true.
  3. Effects — add/delete facts on success: add HasCookedMeal=true, delete HasLog=true, set Hunger=0.1.
  4. Execute() — runtime code: play animation, consume time, call pathfinding. Return Success, Failure, or InProgress.

Procedural vs hand-authored actions

Start with 8–15 core actions (move-to, pick-up, use-station, eat, sleep). Avoid combinatorial actions like CookMealAtKitchenWithAxe — compose small steps instead. For location-specific behavior, use parameterized facts (At(X)) and one GoTo(X) action whose preconditions check reachability via navmesh.

Failure handling

If Execute() returns Failure (tree despawned, path blocked), invalidate the plan and replan from the live world state. Do not assume the planner's predicted effects still hold.

The planning loop

A typical GOAP tick:

  1. Goal selection — pick the highest-priority unsatisfied goal (hunger, cold, job quota). Goals can come from utility AI scores or a simple priority queue.
  2. Plan — run A* (or STRIPS-style backward search) from current state toward goal facts. Cap iterations and plan depth (Harbor uses max 8 actions, 2 ms budget).
  3. Execute — run the first action in the queue; when it completes, pop and continue.
  4. Replan triggers — world facts change materially, action fails, higher-priority goal appears, or a timer expires (re-evaluate every 2–5 seconds even on success).

Performance

Planning is O(branching^depth). Mitigations: limit action set per agent archetype, cache plans keyed by state hash, stagger planner calls across frames, precompute action relevance tables. For 50+ agents, Harbor batches 10 planners per frame at 20 Hz simulation.

Worked example: Harbor Outpost hungry colonist

Initial facts: Hunger=0.85, At(Camp), HasAxe=true, Stockpile(Wood)=0, FireLit=false, HasCookedMeal=false.

Goal: Hunger<0.25 (satisfied by EatMeal which requires HasCookedMeal=true).

Planner output (cost 11):

  1. GoTo(Forest) — cost 2
  2. ChopWood — adds HasLog=true, cost 3
  3. GoTo(Kitchen) — cost 2
  4. LightFire — requires HasLog, sets FireLit=true, cost 1
  5. CookMeal — requires fire, sets HasCookedMeal=true, cost 2
  6. EatMeal — sets Hunger=0.1, cost 1

No designer authored that exact chain. When a storm extinguishes the fire mid-CookMeal, execution fails, facts refresh (FireLit=false), and the planner inserts LightFire before resuming — behavior players read as “the colonist reacted to the weather.” That reactive multi-step problem is awkward for pure FSMs and deep behavior trees without exponential branch duplication.

GOAP vs behavior trees, FSMs, and utility AI

Approach Best for Trade-offs
GOAP Multi-step emergent plans, sims, survival loops, RPG autonomy Runtime planning cost; harder to debug than visual trees
Behavior tree Combat NPCs, designer-ordered priorities, fast iteration Long action chains require huge trees or duplicated subtrees
FSM Player controllers, simple patrol-guard, animation states Transition explosion when needs combine
Utility AI Choosing among competing goals (flee vs fight vs heal) Does not inherently sequence many dependent steps

Hybrid stacks are common: utility AI picks the goal (SatisfyHunger vs Rest), GOAP plans the steps, behavior tree leaves execute individual actions with animation polish. Match the tool to the problem — see emergent gameplay design for when procedural agent stories help retention.

Engine and middleware notes

  • Custom planners — Most teams roll lightweight GOAP in C#, C++, or Rust; data lives in JSON or ScriptableObjects.
  • Unity — Assets like “CrashKonijn GOAP” or bespoke STRIPS implementations; pair with navmesh agents.
  • Unreal — No first-party GOAP; community plugins or plan layers above Behavior Trees.
  • Godot — GDScript planners work for small agent counts; profile A* on web exports carefully.
  • Server authority — In multiplayer, run planners on the server; clients play animations from replicated action IDs.

Pitfalls

  • Oversized fact sets. Tracking every object in the world chokes the planner; scope facts to agent relevance.
  • Monolithic actions. Combining move+chop+carry into one action removes replanning flexibility and reuse.
  • Stale plans. Never replanning after world events produces NPCs cooking on unlit fires.
  • Zero-cost actions. If all actions cost 1, plans ignore distance and risk; tune costs to match gameplay values.
  • Missing failure edges. Actions that always return Success hide bugs; propagate Failure to the planner.
  • Debugging without visualization. Log planned chains and world-state diffs; replay files are essential for sim games.
  • Planning every frame. Throttle replans; execution should dominate CPU, not search.

Production checklist

  • Define a minimal fact vocabulary shared across agent types.
  • Author 8–20 composable actions with explicit pre/effects.
  • Assign non-uniform costs reflecting time, danger, and stamina.
  • Cap plan depth and planner milliseconds per agent per frame.
  • Separate perception updates from planner input snapshots.
  • Replan on action failure, major fact change, and periodic timer.
  • Log plan strings in development builds with state hashes.
  • Unit-test action preconditions and effects without the full scene.
  • Profile agent count scaling before shipping open-world sim loops.
  • Document hybrid boundaries (utility picks goal, GOAP plans, BT executes).

Key takeaways

  • GOAP searches action sequences toward symbolic goals — emergent multi-step behavior without scripting every chain.
  • Small reusable actions with clear preconditions and effects — compose complexity instead of baking it into monolithic states.
  • Replanning is mandatory — the world changes; successful sims replan often and cheaply.
  • Hybrid stacks win in production — utility for goal choice, GOAP for sequencing, BTs for combat polish.
  • Profile planner budgets early — GOAP does not scale to hundreds of agents without caps and batching.

Related reading