Skip to content
Bit Quirky Behavior Trees and
State Machines

Search documentation

All topics and APIs

Close returns focus to Search.

What are you looking for?

Try a common topic or enter a complete API identifier.

Browse the reference instead

Esc closes · Tab reaches results · Enter opens the focused link

v0.6.0
Menu

States and lifecycle

Put setup, ongoing work, and cleanup in the group where each belongs, then choose how the group runs and when the mode counts as done.

A stomped Platformer enemy has to stop moving, stop hurting the player, and look defeated. A state gives each of those jobs a place to live and a moment to happen.

Cleanup is where modes go wrong. The enemy takes the stomp, the graph moves to the defeated mode, and the character keeps drifting along its patrol because the code that stops movement never ran. The same failure in reverse is a mode whose setup runs every frame instead of once, so an animation restarts forever.

EnemyStateMachine.bqbehavior in the Platformer sample answers both with grouping. Patrolling advances the patrol while it is the mode. Defeated stops movement, makes the enemy harmless, and applies the defeated look, all in Active Update, all once.

  • A mode with one-time setup: acquire a target, start an animation, raise a flag your components read.
  • A mode with finite work whose end matters, like the Platformer guard walking to its post before the machine moves on.
  • A mode that owes the next mode a clean handover: clear movement intent, release a reservation, hide a marker.
Entry runs both of patrolling's actions Together and reports Complete once; Active Update then starts its single Once pass and holds Running.
Entry runs both of patrolling's actions Together and reports Complete once; Active Update then starts its single Once pass and holds Running.

DocumentationStateControlsLive.bqbehavior gives patrolling two Entry actions, raise the alert and face the patrol route, with Run set to Together. The rail is the honest readout: the group header goes from Entry 2 Running to Entry 2 Complete while Active Update 1 Running pass 1 takes over below it, and Exit 0 Waiting sits untouched until something takes the mode away. On the state card itself only one row shows the running pip at a time, so read the group header rather than the card rows when work is genuinely overlapping.

The defeated state’s rail during Play Mode, after the stomp
Figure 1. The clip above walks patrolling; this still is the same reading on a different mode of a shipped graph. After the stomp, each row in the Platformer enemy’s defeated mode carries its own result and the group above them reads Complete.

DocumentationStateTransitions.bqbehavior under Assets/Platformer/Behavior/Tutorials/ has a state built to be read: alarmed owns all three groups.

  1. Open the graph and select the alarmed state. The rail opens with SELECTED · STATE, the editable name, then the three lifecycle cards.

  2. Read Entry. Its caption says “Runs once when the state becomes active.” Two rows sit under it: sound the alarm and call for backup.

  3. Read the Run row on that same card. It is set to Together, which is why both alarm rows advance in the same update. Switch it to In order and the second row waits for the first.

  4. Read Active Update. It holds one row, sweep the area, so there is no Run control to choose. Lifetime is Repeat, so the row starts a new pass after each completed one.

  5. Read Exit. clear the alert sits there, and the group’s caption says it runs once when switching, finishing, or returning.

  6. Select the action sound the alarm on its own. Its Action card names Group, Position as 1 of 2, and Owning state, and a Group execution card below repeats the group’s Run value, so a row always tells you which group owns it.

  7. Select the investigating state and read Completion > When done. It is set to Return, which is the setting Push and Return needs.

The alarmed state’s rail, from its identity header through its Entry, Active Update and Exit groups to Completion
Figure 2. Three groups, one state, named at the top of the rail. Each carries its own rows, its own caption, and the settings that belong to it.
The Group execution card on the sound the alarm action
Figure 3. A selected row names its Group, its Position as 1 of 2, its Owning state, and the group’s Run policy.

A state with one row shows no Run control, because there is no order to choose. Add a second row and the control appears.

One direct Active Update action inside the patrolling state
Figure 4. A direct action carries its own lifecycle group. The card on the canvas shows which mode owns it.

Lifecycle

Enter
Runs once per fresh activation, before Active Update. A Running Entry row keeps the state in Entry, and a failed row stays visible as the group's result instead of being skipped. Entry has no Lifetime, because once per activation is already its rule.
Active
The mode's work, from direct action rows or one hosted behavior tree. In order advances one unfinished row at a time; Together advances every unfinished row in the same update. Once holds the terminal result; Repeat starts a new pass on the next update.
Exit
One update, after a transition latches and before the destination's Entry. Unfinished work is canceled and unreached In order rows are marked skipped. An empty Exit skips the dedicated update entirely.
Finished
A terminal Active Update result that no transition claimed. Completion decides: Stay keeps the mode, Return pops the activation a Push suspended, Finish ends the machine with Success, Failure, or the result the mode just produced.

Run

  • In order starts one unfinished row at a time. A row that succeeds while later rows remain reports Running for the group, so the next row begins on the following update. A non-success terminal result stops the group and becomes the group’s result.
  • Together advances every row that has not finished during the same update. The group succeeds when all rows succeed; the first non-success terminal result cancels unfinished peers and becomes the group result. This is group scheduling on one update, so your code still runs on the host’s own thread.

Lifetime, on Active Update only

  • Once keeps the terminal result. An On finish transition or a Completion policy can then read it.
  • Repeat begins a new pass on the next update after Success or Failure, unless a transition latched first. Each completed pass is an On iteration boundary.
  • A state with no Active Update rows reaches an empty successful boundary immediately, which is how an actionless mode still gets its transitions and Completion evaluated.

The handoff order

A latched transition does not cut the current update short. The transition fires, Exit is deferred, the source gets exactly one Exit update, and the destination’s Entry starts on the update after that. The rail spells the same sequence out under Lifecycle.

Completion

When done What happens
Stay The mode stays active. Once holds its result; Repeat starts another pass.
Return Exit gets its one update, then the activation suspended by the matching Push becomes active again. Returning with nothing suspended finishes the machine instead: it stops with no result.
Finish Exit gets its one update, then the machine finishes with Success, Failure, or Use result, which publishes the terminal Active Update result.

When it goes wrong

SymptomCheckFix
Setup work runs over and over.Read which group the row sits in on the action’s own rail.Move it to Entry with the Group row, or give Active Update Lifetime Once.
Cleanup never happens.Read whether the transition that fired is Switch or Push, then confirm the row is in Exit.Push suspends without Exit, so put final cleanup behind a Switch handoff.
Only the first Exit row ran.Read Run on the Exit group.Exit gets one update. In order stops at the first row that does not succeed immediately and skips the rest, so use Together when every row must get its turn.
The mode never finishes.Read the Active Update group in Live and find the row that still reads Running.Either let that operation complete or give the mode a Continuous transition that can take it out.
An On finish transition never fires.Read Lifetime on Active Update.Set it to Once. A Repeat group produces iteration boundaries and never a finish boundary.
The lifecycle controls are read-only in Static.Look for a Source compatibility card reading Legacy action list.Press Upgrade lifecycle source once. The graph keeps its current order, Run, and Lifetime, and the three groups become editable.
Full-size image