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

Roll the dice

A Random Selector picks one branch by weight, so an agent stops repeating itself without you writing a shuffler.

Some choices have no best answer, only acceptable ones. A Random Selector draws one branch by weight, and a designer can retune those weights without touching code.

The Horde Survival director has to keep pressure interesting. If a surge always spawns the same swarm, players learn it in two rounds and the tension goes flat. Random picking in code means a weights array, a cumulative sum, and a bug where somebody adds an option and forgets the denominator.

HordeDirector.bqbehavior in the Horde Survival sample puts the surge choice on a Random Selector instead. The weights are authored values, the distribution is shown next to each row, and adding a fourth option is one click.

  • A director or spawner that should vary what it throws at the player, with the odds visible.
  • Idle variety: a guard that sometimes checks the left route and sometimes the right, like choose a search route in DocumentationFlowControls.bqbehavior.
  • A chance of doing nothing at all, which the Direct failure outcome gives you without a dummy branch.

Keep ordered priority on a Selector. Weights are for choices where losing the roll is fine.

Every fresh visit rolls again against the weights, so the cursor lands on the left route three times out of four and on the right route once.
Every fresh visit rolls again against the weights, so the cursor lands on the left route three times out of four and on the right route once.

Several evaluations of the same node, landing on different routes. The left route carries weight 3 and the right carries weight 1, so three draws in four go left over a long enough run.

  1. Open Assets/Platformer/Behavior/DocumentationFlowControls.bqbehavior and select the Random Selector called choose a search route.

  2. Read the Branches card. Each row has the child name, an ENABLED switch, a WEIGHT field, and a FIRST PICK percentage the editor computes for you.

  3. Change the left route weight from 3 to 1. Both FIRST PICK readings become 50%. Set it back to 3 and they return to 75% and 25%.

  4. Set a weight to 0. The row stays authored and its reading becomes Never, which is how you park an option without deleting it.

  5. Add the selector’s own failure chance with the Direct failure row above the branches, then give it a weight. It joins the same denominator as the branches.

  6. Use + Add on the Branches header to create another outcome when you need a third route.

Random Selector with two weighted branches
Figure 1. The weights live on the edges. The rail turns them into the percentage you actually care about.

Result

Success
The child it drew returned Success. The selector stops there.
Failure
Every candidate has been drawn and failed, or the Direct failure outcome was drawn, or no candidate has a usable positive weight.
Running
The drawn child is still working, or a child failed and the selector has just drawn a replacement.
  • A draw is weighted and without replacement. A child that returns Failure is removed from this pass’s candidate set and the selector draws again from what remains.
  • Direct failure stays eligible on every redraw until it is picked or the pass ends. Absent is different from present with weight 0: absent is outside the denominator, and zero can never be drawn.
  • Only Failure triggers a redraw. Blocked, Interrupted, Timeout, and Authority mismatch travel straight up to the parent, so a guarded child that reports Blocked ends the pass rather than passing the turn to a sibling.
  • Each agent carries its own random state, so two enemies on one graph draw independently. The state advances one value per draw.
  • A selector supports up to 64 direct branches, which is the width of its per-agent candidate mask. Direct failure is stored separately and costs none of the 64.
  • Weight text that is empty, negative, or not a number is kept for repair and blocks a valid bake. The editor leaves your typing alone instead of substituting a default.

When it goes wrong

SymptomCheckFix
One branch runs every time.Read the FIRST PICK column for the other rows.Raise a weight above zero and switch the row to Enabled.
The selector reports Failure and no child ever took the status pill.Look at the Direct failure row; a drawn Direct failure ends the pass without a child.Lower or remove that weight if you did not want a do-nothing outcome.
A low-weight branch runs more often than the percentages suggest.Check whether the high-weight branch fails.Nothing to repair. A failed branch drops out and the rest redraw.
Validation rejects the node.Confirm at least one enabled branch or Direct failure has a positive finite weight.Type a valid number in the WEIGHT field for one of them.
You want a shuffled order instead of one pick.This node draws one outcome per pass.Model the order in your own code and bind the result, or accept the redraw behavior.
Full-size image