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

Method

Call one exact method and decide what its answer means to the graph.

A method binding calls the method you already wrote, with the arguments you choose, and turns its return value into a node result.

The Racing Line CPU driver asks questions its race services already answer. Has this driver finished? How far behind the player is it, signed? What is the smoothed pace gap after this frame? Those are three methods on services the game uses anyway.

Rebuilding that arithmetic inside the graph would give you two versions of the same rule, and the graph’s copy would be the one nobody remembers to update. CpuRace.bqbehavior calls the real ones: HasDriverFinished(int) for the gate, SignedGapToPrimaryPlayerMeters(int) stored straight into a variable, and SmoothPaceGap(int, float, float, float, int) fed from four variables and one projected member value.

  • The return value decides the next step, like the Platformer check fall node calling ShouldRespawnFromFall(-10f) and comparing the result with true.
  • You need the answer in a variable for a later node, which is what Store is for.
  • The call takes time. A coroutine or an awaitable keeps the node Running until it finishes; waiting and cancellation covers that path.
A method member node bound to the player rules
Figure 1. One node, one exact call. The card names the method, not a wrapper class you had to write.
The Racing Line overtake decision selected, with its two Project arguments in the rail
Figure 2. Racing Line’s overtake decision. Both arguments come from the adapter’s own members through Project, so the call reads them by name at the moment it runs.
The method rail: Target, Member, Arguments, and the Result card the rail scrolls into
Figure 3. The four cards of a method binding, in the order you fill them.
  1. Add method from the picker, under ACTIONS, described as “invoke a c# method on a target”.

  2. Finish the Target card so the picker has a type to list. See targets and resolve.

  3. Use Member > Change and pick the exact overload. Open the disclosure to confirm Kind, Signature, and Returns.

  4. Close any Generic types slot the method declares. Arguments and Result stay locked until every type argument is chosen.

  5. Fill the Arguments rows. Each row offers Constant, Blackboard, and Project, plus Default when the parameter has a real compile-time default.

  6. Set Result. A member that returns a value offers Test and Always; a member that returns the product’s own node result also offers Returned.

  7. For Test, choose the operator, the compared value, and the When true and When false outcomes under OUTCOMES.

Result

Success
The mapped outcome for this return was succeeded, or a deferred call completed with succeeded.
Failure
The mapped outcome was failed, or a deferred call completed as failed.
Running
An outcome maps to running, so the node calls again next evaluation, or a coroutine or awaitable is still outstanding.

Result forms

Form What it does
Returned The method returns the product’s node result and the node reports exactly that, including results beyond success and failure. Offered only for that return type.
Test Compare the return. Value types use <, ≤, =, ≠, ≥, >; reference types use is and is not. Then map When true and When false.
Always Report one fixed result whatever came back. The seven choices are succeeded, failed, running, interrupted, blocked, timeout, and authority.
Store An independent destination. Storing a value never implies success, and it does not replace an out destination, because a return and an output are different values.

Rules that catch people out

  • Store and result mapping are separate choices. One call can write its return to a variable and use that same return to decide the node result.
  • A mapping where every possible outcome is running is refused, because such a node could never finish.
  • One activation owns one invocation. A method is not called again while its coroutine or awaitable is still outstanding, and a late completion cannot resume a later activation.
  • A thrown call reports a fault rather than your authored failure. The runtime records the fault with the graph, the node, and the member, and the node completes as faulted, which travels up to the root so the reason survives.
  • Outputs commit as one batch in declaration order after a normal return, before result mapping. A call that throws commits none of them.

When it goes wrong

SymptomCheckFix
The Result card is locked.Look for an unclosed Generic types slot.Choose a concrete type for every type parameter.
The node succeeds when the game clearly failed.Read the Test operator and both outcome rows.Map the outcome you meant. A stored value has no effect on the result.
The method is called every frame.One outcome maps to running, which is polling by design.Map to succeeded or failed, or bind a coroutine or awaitable if the work genuinely takes time.
The node reports a fault you did not author.Read the fault trace on the agent: a thrown member, a lost target, or a coroutine exception.Fix the member. A fault is deliberately not an authored failure.
Your out value never arrived.Confirm the call returned normally.A throw commits no outputs; a normal false return still commits them.
The overload you want is not in the picker.Confirm access level and parameter shapes on that exact declaration.Make it public, or add [BehaviorMember] to that exact declaration.
Full-size image