Skip to content

FAQ and Troubleshooting

AzureDoom edited this page Aug 29, 2026 · 1 revision

FAQ and Troubleshooting

"My entity's AzureCortex tree never seems to run"

Check the basics first, in order:

  1. Are you actually calling runtime.tick() from your entity's tick() method, guarded by !level().isClientSide() && isAlive() && !isNoAi()? AzureCortex does nothing on its own, nothing ticks a CortexRuntime for you.
  2. Is isNoAi() true on the entity (e.g. spawned via /summon ... {NoAI:1}, or a passive display entity)? CortexRuntime.tick() no-ops immediately if agent.isNoAi().
  3. Did you remove the conflicting vanilla goals (NearestAttackableTargetGoal, movement goals, etc.) from registerGoals()? Leaving both vanilla's own targeting/movement goals and AzureCortex active on the same entity means they'll fight over the same navigator and target, see Full Example Walkthrough step 4.

"My agent keeps flickering between two actions"

This is almost always a min-commit/priority-tuning issue, not a bug in the framework:

  • If two goals score too closely and minCommitTicks is too low, GoalExecutor.shouldReplan will let the planner swap between them constantly. Raise minCommitTicks, or bias the scoring further apart.
  • If two tree branches have equal or near-equal priority and their preconditions both hold intermittently (e.g. a target flickering in and out of range), consider a CooldownGate around the noisier branch, or tighten the precondition's hysteresis (e.g. require a slightly larger "leave" threshold than the "enter" threshold).
  • Check whether PlanInvalidation is firing more than expected, a target's distance bucket flipping back and forth right at a bucket boundary will force replans repeatedly. WorldStateSnapshot's buckets are deliberately coarse for this reason; if you're still seeing boundary flicker, that suggests the agent is genuinely hovering at a boundary (e.g. orbiting at maximum engagement range) worth addressing in the action's own movement logic.

"An action never gets interrupted even though something higher-priority should win"

Check its interruptCategory(). An action reporting LOCKED (or isInterruptible() == false) can only be preempted by an EMERGENCY candidate, a higher-priority NORMAL candidate will never take over. This is deliberate (see Core Concepts) but is a common surprise the first time someone builds a "committed" action and then can't figure out why nothing else ever wins.

"My emergency goal gets committed but the action doesn't actually take over"

GoalUrgency.EMERGENCY on the GOAP side only controls whether the planner is allowed to replan immediately — it says nothing about tree-side preemption. The resulting action also needs a high enough priority (and/or an InterruptCategory.EMERGENCY on the action itself, or via BehaviorResult.runEmergency) to actually win against whatever's currently running in the tree. See the eat-to-heal branch in Full Example Walkthrough for a worked example of getting both sides to agree.

"Pathfinding returns an empty list even though a path clearly exists"

  • Check maxRange, both pathfinders cap search cost by Manhattan distance from the start; a path outside that range is never found. AStarPathfinder also caps at 2,000 expanded nodes (6,000 for CrawlTraversalEvaluator) regardless of range.
  • If you're using MovementCapability/CrawlCapability and haven't implemented them on your entity, you get the fully-permissive defaults, that shouldn't block a path, but double-check you haven't accidentally marked something as a hazard/non-passable that should be walkable.
  • Remember both pathfinders return the best partial path rather than an empty list whenever a full route can't be found within budget, so "empty list" specifically means no progress was made at all (e.g. start position itself isn't standable), not merely "goal unreachable."

"How do I persist blackboard/memory state across a save/reload?"

You don't get this for free, both Blackboard and AgentMemory are transient, in-memory stores discarded when the entity is removed from the world (including on unload/save). If something needs to survive, persist it yourself via your entity's addAdditionalSaveData/readAdditionalSaveData and re-populate the relevant blackboard/memory key on load.

"Can I use AzureCortex without the GOAP layer at all?"

Yes. CortexRuntime only requires a BehaviorNode tree and (optionally) a Sensor, nothing about GoalPlanner, PlannedGoal, or GoalExecutor is mandatory. A tree built entirely from PrioritySelector/Condition/ActionNode against blackboard state you manage yourself (without ever touching ACTIVE_GOAL_TYPE) works fine for simpler agents that don't need multi-goal planning.

"Do I need TargetSensor?"

Only if your agent targets other entities. Purely environmental/wandering agents (no combat, no pursuit) can use CortexRuntime with a null sensor and a tree built from movement/utility actions alone.

"Where do I ask questions or report bugs?"

Next

If your question isn't answered here, the Full Example Walkthrough and the relevant reference page (linked from Home) are the next places to check, most of AzureCortex's classes carry substantial Javadoc explaining why a given piece of behavior exists, not just what it does.

Clone this wiki locally