Performance Tuning¶
The RGS GOAP Framework is built for performance from the ground up. This page covers the architectural decisions that make it fast, the limits you need to know, and how to tune for large agent counts.
Built-In Performance Features¶
Burst-Compiled Planning¶
The planner runs as a Unity Burst-compiled IJob on a worker thread:
- Zero managed allocations during planning
- Planning never blocks the main thread
- O(log N) open-set operations via NativeMinHeap
- 128-bit bitmask state representation for fast comparison
ContentRevision Cache Gate¶
Every blackboard Set* call increments a ContentRevision counter. Before scheduling a Burst job, the planner checks whether the revision has changed since the last plan:
- Unchanged → skip planning entirely (no Burst job scheduled)
- Changed → schedule a new plan
This prevents redundant replanning when the world state hasn't changed. ForceReplan() bypasses this gate when needed.
Plan Comparison¶
When a new plan is produced, it's compared against the current plan from the current step onward. If the plans match, the executor continues uninterrupted — no OnStop/OnStart cycle on the active strategy.
Staggered Sensor Updates¶
Sensors don't fire every frame. The default interval is 0.5 seconds, and first-tick timing is staggered using a deterministic offset based on each agent's InstanceID. This distributes sensor polls evenly across frames, preventing CPU spikes.
Goal Preemption is Lightweight¶
EvaluateBestGoal() is O(goals) with a few float operations each. At the default 0.5-second interval, this is negligible even with hundreds of agents.
Hard Limits¶
128 Beliefs Maximum¶
TagMask128 uses 4x 32-bit integers to represent world state. Each unique GoapBeliefInstance (by InstanceId) in the brain consumes one bit. This limit cannot be raised without replacing the planner architecture.
In practice, most brains use 10–30 beliefs. Monitor your count during development via the Initialize() logs.
Warning
The 128-belief limit is across all states in a single brain. If beliefs are shared across states (same InstanceId), they only count once.
Tuning Parameters¶
MaxPlannerIterations¶
Default: 2000. Caps A* search as a safety bound.
- Lower (500–1000) — faster fail for complex/impossible plans, good for many agents
- Higher (3000–5000) — allows deeper search for brains with many actions
- If plans fail with
MaxIterationsReached, increase this value or simplify the state's action set
Sensor UpdateInterval¶
Default: 0.5s. How often each sensor fires.
- Lower (0.1–0.2s) — more responsive but higher CPU cost
- Higher (1.0–2.0s) — cheaper but agents react slower to world changes
- Tune per-sensor based on importance: vision sensors might need 0.2s, waypoint sensors can use 1.0s
Goal Reevaluation Interval¶
Default: 0.5s. How often CheckForBetterGoal() runs.
- Lower — faster goal switching, slightly more CPU
- Higher — less responsive to priority changes, cheaper
Transition Check Interval¶
Default: 0.1s. How often FSM transitions are evaluated.
- Keep this fast for responsive state switching
- The cost is minimal (just belief evaluation, no planning)
Debug Log Gating¶
All diagnostic logging in the framework is gated behind debug flags:
| Flag | On Component | What It Controls |
|---|---|---|
Debug Plan Search |
GoapAgent | A* search steps, goal evaluation, plan results |
DebugExecution |
Executor (internal) | Action start/stop, post-process entry/exit |
Danger
Never leave debug flags enabled in production. String interpolation + stack trace capture at 1000+ agents destroys performance. Only unconditional logs are true initialization errors (null brain, null state).
Scaling Guidelines¶
10–50 Agents¶
Default settings work well. No tuning needed.
50–200 Agents¶
- Ensure all debug flags are off
- Stagger sensor intervals (not all sensors at 0.5s)
- Keep action counts per state to 3–8
- Use
MaxPlannerIterationsof 1000–2000
200+ Agents¶
- Profile sensor costs (Physics.OverlapSphere, raycasts)
- Consider higher sensor intervals for less critical sensors
- Use the ContentRevision gate aggressively (avoid unnecessary blackboard writes)
- Pool NavMeshAgent queries if movement is a bottleneck
- Monitor Burst job scheduling overhead in the Unity Profiler
Performance Checklist¶
Before shipping:
- [ ] All
Debug Plan Searchflags are off - [ ] All
DebugExecutionflags are off - [ ] No
Debug.LogorDebug.LogWarningin per-frame strategy/post-process code - [ ] Beliefs contain no physics queries (raycasts, sphere checks) — those belong in sensors
- [ ] Sensor intervals are tuned per-sensor based on importance
- [ ] Total beliefs per brain are well under 128
- [ ]
MaxPlannerIterationsis set appropriately for your brain complexity - [ ] Profiler shows no Burst job scheduling spikes
See Also
- Blackboard — ContentRevision — How the planner avoids redundant replanning
- Sensor Controller — Timing Details — How staggered sensor polls work
- GOAPAgent — Inspector Settings — Where to set the tuning parameters above
- Glossary — Quick definitions for ContentRevision, Planner, and other terms
What's Next¶
- The Planning Loop — Understand the frame execution order for timing optimization.
- Runtime Debugging — Use debug tools without leaving them on in production.
- Troubleshooting — Diagnose performance-related issues.