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

Transitions

Decide when a mode ends, what has to be true, and which rule wins when two of them are true at once.

A transition is the sentence “when this is true, that mode takes over”. The Platformer enemy leaves patrolling the moment stomped is no longer zero, and you can point at the row that did it.

Two rules are true in the same update. The guard hears a noise and the alarm is armed: one row says investigate, another says raise the alarm. Both predicates hold, and the machine has to pick one. If the answer feels random, the machine is not wrong, the priority just lives somewhere you have not looked yet.

Priority is authored order, and the rail shows it as a draggable list. Line crossings on the canvas and card positions decide nothing.

  • A fact that should interrupt the current mode right now: health drops, the player comes into view, input arrives.
  • Finite work whose end is the reason to move on, like the Platformer guard reaching its post before the machine advances.
  • A hosted tree or child machine whose Success and Failure need different destinations.
One continuous transition: player_visible turns true, the pill takes the tick and reads FIRED, and chasing becomes the active state.
One continuous transition: player_visible turns true, the pill takes the tick and reads FIRED, and chasing becomes the active state.

DocumentationStateControlsLive.bqbehavior runs that handoff. The transition pill on the canvas carries its own predicate text and picks up a FIRED badge on the update it takes, so the row that moved the machine is the row you can see. The rail agrees: Active state reads chasing, Active action reads chase the player, Last transition reads player spotted, and Cause reads player_visible.

A transition between patrolling and chasing, its pill reading player_visible == true
Figure 1. A transition is the labeled connection between two modes. Its trigger decides when the handoff may happen.

DocumentationStateTransitions.bqbehavior under Assets/Platformer/Behavior/Tutorials/ has a patrolling state with three outgoing rows, which is what makes priority visible.

  1. Open the graph and select the transition alarm raised. The rail opens with From and To navigation rows, so you never have to guess which pair of modes a row joins.

  2. Read the Evaluate card. When is Continuous, and the tag beside the card heading repeats the cadence.

  3. Read the Trigger card. Source is Conditions, the group is set to All conditions, and two predicate rows compare noise_heard with true and alarm_ready with true. All has to hold, so this row wins only when the guard can actually raise an alarm.

  4. Select noise heard. Same cadence, but its group reads Any condition: either a noise or a reached post sends the guard to investigate.

  5. Read the Precedence card at the bottom of either rail. Its caption is the rule: “The first matching transition wins. Drag to change the order.” alarm raised sits above noise heard, so an armed alarm beats an investigation.

  6. Select sweep again. When is On finish with Result set to Success, so this row waits for patrolling to finish a successful pass. Its From and To are the same state, which is why it also carries a Re-entry card.

The Evaluate, Trigger, and Kind cards on a continuous transition
Figure 2. One continuous row, top to bottom: where it goes, when it may fire, what has to be true, and what happens to the mode it leaves.
Two predicates in an All group on the alarm raised transition
Figure 3. All conditions: the guard raises the alarm only when it heard something and the alarm is armed.
The same trigger card on noise heard, set to Any
Figure 4. Any condition: a noise or a reached post is enough to send the guard to investigate.
On finish with its Result filter set to Success
Figure 5. The tag beside the card heading carries both halves of the cadence at once.
The sweep again transition rail, down to the Precedence card listing patrolling’s three outgoing rows
Figure 6. The same three rows appear whichever of them you select. Row one wins when two of them are true.

Cadence: when a row is even eligible

When Eligible at Reach for it
Continuous The boundary that opens every update, and again right after Active Update produces a terminal result A fact that should interrupt the mode: perception, health, input
On finish While a Once Active Update holds its terminal result Leaving after finite work has actually finished
On iteration Once at each completed Repeat pass Reconsidering after one full pass instead of mid-pass

Not every source offers all three. Any State rows are Continuous only, because Any State has no Active Update whose finish could arm a row, and the rail says so under the control. A Referenced State Machine source offers Continuous or On finish, since a child machine completes but has no passes.

Trigger: what makes it true

  • Conditions is an ordered predicate group over readable graph values. All conditions stops at the first false row; Any condition stops at the first true row. Authored order is evaluation order, so put the cheap decisive comparison first.
  • Event listens for one result event the same source state exposes from its hosted tree or child machine. Conditions and Event are alternatives on one row; choosing Event leaves the predicate group dormant so you can switch back.
  • None appears only where the cadence itself can arm the row, which means On finish or On iteration on an ordinary state. A Continuous row with no trigger is refused by validation, because it would take over before the mode could do anything.

Each predicate compares a readable value with a typed constant or another compatible readable value. The delivered operators are <, <=, ==, !=, >=, >, narrowed by type: a bool keeps equality and inequality without ordering. Both sides have to be declared and readable by that transition, and a missing constant is an error rather than a silent zero.

Result: which terminal result counts

For On finish and On iteration, Result accepts Any, Success, or Failure. Running never satisfies a filter, and a runtime fault never counts as authored Failure. A Continuous row cannot carry a filter at all; validation rejects the combination instead of ignoring it.

Order: which row wins

  1. The active machine’s Any State rows, in authored order. A row whose destination is already the active mode is skipped, so a global predicate that stays true does not restart its own destination.
  2. The active state’s own rows, in authored order.
  3. The state’s work for this update.

Right after Active Update produces a terminal result, the same scan runs again with the finish and iteration rows included. The first match wins, at most one transition fires per update, and Completion applies only when nothing matched.

A predicate that faults takes the machine to Faulted rather than falling through to the next row. A predicate the executing authority may not read is declined, and the scan moves to the next row.

Kind and re-entry: what happens to the mode you leave

  • Kind > When taken set to Switch cancels the work the source owned, discards suspended activations, gives the source one Exit update, then enters the destination.
  • Push suspends the source without Exit and enters the destination as a nested activation. Push and Return has the whole story.
  • A row whose From and To are the same state gets a Re-entry card. Restart runs the ordinary Exit and Entry handoff and starts the mode’s progress over. Resume keeps the progress and runs neither group, which is how sweep again gets another patrol pass out of the same activation. Resume is legal only on a self transition.

When it goes wrong

SymptomCheckFix
The wrong destination wins.Read Any State first, then the Precedence card on the active state.Drag the row that should win above the row that should lose.
The row never fires.Read its Evaluate card against the state’s Lifetime.On finish needs a Once Active Update; On iteration needs Repeat. A Running action has reached neither boundary.
Validation refuses a Continuous row.Look at its Trigger card for a condition or an event, and at its Evaluate card for a Result filter.Give it a trigger, and move any result filtering to an On finish row.
The predicate looks right and still reads false.Select the row and read both operands, then read the same values in the Live blackboard.Point the predicate at the value the game actually writes, or fix the constant. Live shows the host-authoritative reading.
Two predicates both matter and only one is checked.Read the group mode above the rows.All conditions requires every row. Any condition stops at the first true row, which is what you want for alternatives.
An Event row cannot find its event.Select the source state and read its Result events card.Expose Success or Failure on that state. The picker lists only the ids the row’s own source exposes.
The mode restarts and loses its progress.Read the Re-entry card on the self transition that fired.Set On re-entry to Resume to keep the activation, or leave Restart when stale progress would be unsafe.
Full-size image