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

Conversion

The exact set of type conversions a binding accepts, and what happens to everything outside it.

A binding accepts six kinds of type conversion and refuses everything else while you are still authoring. This page is the list.

Silent conversion is where graph tools go to die. A float quietly truncated into an int, a downcast that works until the day it does not, a ToString nobody asked for. The bug shows up in a playtest as a guard walking to the wrong place, and the graph looks correct.

So the accepted set is small enough to memorize, and a pair outside it is refused at authoring time with a named reason. The failure lands where you can fix it: in the editor, before the bake produces anything.

  • A float member you want in an int variable, which is the narrowing the editor refuses outright.
  • A Vector3 member beside a float3 variable, which is Horde Survival’s most common surprise.
  • A List<Vector2> variable feeding a Vector2[] parameter, which is the one collection conversion that is accepted.
A member the picker keeps visible and unpickable, with its reason
Figure 1. A member the picker keeps visible and unpickable, with its reason
Conversion Example Direction
Exact type float variable into a float parameter Either
Implicit numeric widening int variable into a float parameter Either, separately per leg
Enum to its exact underlying integral a MovementIntentMode variable read as int Either
Underlying integral to its exact enum an int variable written to a MovementIntentMode field Either
Reference assignment to a base class or implemented interface a Rigidbody variable into a Component parameter Where the assignment is legal
List to array of the same element type a List<Vector2> variable into a Vector2[] parameter, where the member accepts a matching collection Into the member

Widening follows C# exactly: sbyte to short, int, long, float, double; byte to short, ushort, int, uint, long, ulong, float, double; short to int, long, float, double; ushort to int, uint, long, ulong, float, double; int to long, float, double; uint to long, ulong, float, double; long and ulong to float, double; char to ushort, int, uint, long, ulong, float, double; float to double.

  • Numeric narrowing in either direction, including float to int and long to int.
  • One enum for another, and an enum to an integral type that is not its own underlying type.
  • Downcasts, user-defined conversion operators, Convert coercions, and anything else not in the table.
  • Boxing, unboxing, and nullable wrapping: they are absent from the vocabulary rather than partially supported.
  • Two different structs of the same size. An unmanaged value needs exact CLR identity, so UnityEngine.Vector3 and Unity.Mathematics.float3 are two types and stay two types.
  • Approximate collection matches. An array, a List<T>, and a Dictionary<K, V> each need exact identity, apart from the one list-to-array case above.
  • Anything at all on an index argument of an indexed property. Those take the exact type.

string has no conversion family, because a string is a managed reference like any other. A string constant is accepted where the parameter is exactly string, and the canonical way to write an absent reference constant is null.

Compatibility is evaluated per leg:

  • A variable into a member needs the variable’s type to reach the member’s type.
  • A member into a variable needs the member’s type to reach the variable’s type.
  • two-way needs one exact type on both sides.
  1. Open Assets/Platformer/Behavior/DocumentationMemberNodes.bqbehavior and select read coin goal. It surfaces LevelRules.coinUnlockThreshold, an int, as coin_unlock_threshold.

  2. Select check fall. Its one argument, playerVerticalPosition, is a float authored as the constant -10.

  3. Switch that argument’s source to Blackboard and pick coin_unlock_threshold. It binds, because int widens to float and each leg is judged on its own.

  4. Now ask for the refusal. Point read coin goal at LevelRules.moveSpeed, a float, while its surfaced value is still an int.

  • The check runs while you author, and a rejected pair is recorded as an unsupported conversion with the code member-unsupported-conversion. The editor labels the row incompatible and keeps your binding for repair.
  • A bake with that error produces no artifact, so a conversion the rules reject never reaches a running game.
  • A constant is converted and range-checked during the bake. Constants can be authored for bool, the signed and unsigned integrals including char, finite float and double, an enum by member name or by its exact underlying literal, and null for a reference.
  • Generated call sites carry the conversion as a plain C# cast, so there is no conversion table consulted at tick time.
  • On the entity path the same table applies, restricted to the carried value kinds, and reference assignability is dropped because that path has no references to assign. Numeric widening is applied when the argument frame is materialized.

When it goes wrong

SymptomCheckFix
The variable you want is missing from a Blackboard source list.Compare its declared type with the parameter type.Declare the type the member uses, or add an overload that takes what you have.
Two-way is refused on a pair that works one way.One leg is a widening conversion.Make both types identical, or use two one-way bindings with the ownership you actually want.
A float3 member refuses a Vector3 variable.These are two exact CLR types.Declare the exact type the member uses, or convert inside your own code.
An enum variable will not bind to a differently sized integer.Only the enum and its own underlying type convert.Declare the underlying type of that enum, or expose the member with the enum type.
Your implicit operator is ignored.User-defined conversions are outside the accepted set.Expose a member that already takes or returns the type you have.
An indexer index is refused even though it would widen.Index arguments take no conversion at all.Supply the exact index type.
Full-size image