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

Catch-up pressure

Build a rubber band as one named blackboard value, then branch on it, so the assist is visible instead of buried in a curve.

A rubber band nobody can see is a rubber band nobody can tune.

A CPU car that falls behind should claw back, and a player who is winning should feel pursued. Done as a hidden multiplier inside the driving code, nobody can answer “why did that car suddenly catch me”, and tuning it means reading a function.

Accumulate the assist into one named value, then let a branch read that value out loud.

CpuRace.bqbehavior in Racing Line builds it in order inside its drive Sequence: sample the signed gap, smooth the gap, plan a bounded pace multiplier, derive a cornering pace, then a surge branch Selector. Its first child is the member condition catch-up pressure crosses the surge threshold, bound to Pacing.AdvanceCatchUpPressure, whose second parameter is ref float catchUpPressure. One evaluation reads the blackboard value catch_up_pressure, lets the game’s own rubber-band rule move it, writes it back, and compares the new value against 3. When it does not cross, the fallback child holds the branch neutral.

The surge branch in the editor: a surge branch selector, a catch-up pressure condition comparing catchUpPressure after the call against three, and a neutral fallback.
Figure 1. CpuRace in Static. The threshold is a comparison you can read off the card, and the value it compares is the one the condition’s own call just wrote.

The bounded multiplier matters as much as the branch. Pressure accumulates, and the plan step clamps what it is allowed to do, so the assist never becomes a teleport.

No wrapper method sits between the graph and Pacing. A ref parameter is the normal C# shape for “adjust this value in place”, and the graph binds it as written. Arguments and results shows the cards.

Bind a method like this once. It changes the value it is handed, so a second node bound to it would move the pressure twice per tick and quietly double every rate the method applies. When you want the adjustment and the test in different places, bind the adjustment on a method node and test catch_up_pressure with a plain Condition instead.

  • Method for each step of the plan, all of them in the game’s own driving code.
  • Member condition for the pressure itself: one call adjusts it, and the same evaluation tests the result.
  • Selector for the surge branch, with an explicit neutral fallback so the branch always resolves.
  • Repeat at the root, keeping the decision loop alive for the whole race.

Name the pressure, keep it on the blackboard, and branch on a threshold instead of scaling silently. A designer can then watch the number climb in Live and say “that is too fast” with evidence.

Full-size image