Director with weighted choices
Give a wave director a Random Selector with real weights so each surge feels different without feeling arbitrary.
On this page
Weights on a Random Selector are graph data, so the designer who wants brutes rarer edits a number.
The problem
Section titled “The problem”Every wave the same. Players learn the pattern and the tension goes. Randomizing it in code means a switch on Random.Range buried in a spawner, and the designer who wants brutes to be rarer has to file a ticket.
The shape
Section titled “The shape”A state machine for the phases, and a Random Selector inside the phase that needs variety.
HordeDirector.bqbehavior holds three states: Build Up, Surge, and Relax, with transitions that read elapsed time and the live enemy count. The Surge state runs a Random Selector named Choose Surge whose three children carry weights.

Surge carries a repeat lifetime, so each pass through the state rolls again. The weights are graph data, which means tuning the feel of the game is an edit in a window.
Nodes it uses
Section titled “Nodes it uses”- Random Selector for the weighted pick.
- State and Entry State for the three phases.
- Transition with condition groups: Build Up leaves on an All group of elapsed time and enemy count, while Surge leaves on an Any group so either a timeout or a crowd ends it.
- Blackboard values for every threshold, including
build_up_duration,surge_duration, andsurge_live_enemy_limit.
Reuse it
Section titled “Reuse it”The director does not spawn anything. Each action asks the game’s own spawner for a flavor of wave, and the game owns budgets, pooling, and placement. That split is what lets you retune pacing without touching spawn code.
- Attack with cooldown: what an individual enemy does once a surge spawns it.
- Horde Survival chapter: the benchmark scene and how to run it.