Roll the dice
A Random Selector picks one branch by weight, so an agent stops repeating itself without you writing a shuffler.
On this page
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 problem
Section titled “The problem”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.
When to reach for it
Section titled “When to reach for it”- 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.
See it
Section titled “See it”
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.
-
Open
Assets/Platformer/Behavior/DocumentationFlowControls.bqbehaviorand select the Random Selector called choose a search route. -
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.
-
Change the left route weight from
3to1. Both FIRST PICK readings become 50%. Set it back to3and they return to 75% and 25%. -
Set a weight to
0. The row stays authored and its reading becomes Never, which is how you park an option without deleting it. -
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.
-
Use + Add on the Branches header to create another outcome when you need a third route.

How it decides
Section titled “How it decides”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
Section titled “When it goes wrong”When it goes wrong
| Symptom | Check | Fix |
|---|---|---|
| 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. |
- Director with weighted choices: the whole Horde surge pattern.
- Choose: ordered priority instead of odds.
- Random Selector reference: every field on the card.