Conversion
The exact set of type conversions a binding accepts, and what happens to everything outside it.
On this page
A binding accepts six kinds of type conversion and refuses everything else while you are still authoring. This page is the list.
The problem
Section titled “The problem”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.
When it bites
Section titled “When it bites”- A
floatmember you want in anintvariable, which is the narrowing the editor refuses outright. - A
Vector3member beside afloat3variable, which is Horde Survival’s most common surprise. - A
List<Vector2>variable feeding aVector2[]parameter, which is the one collection conversion that is accepted.
See it
Section titled “See it”
The accepted set
Section titled “The accepted set”| 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.
What is refused
Section titled “What is refused”- Numeric narrowing in either direction, including
floattointandlongtoint. - One enum for another, and an enum to an integral type that is not its own underlying type.
- Downcasts, user-defined conversion operators,
Convertcoercions, 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.Vector3andUnity.Mathematics.float3are two types and stay two types. - Approximate collection matches. An array, a
List<T>, and aDictionary<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.
Direction changes the answer
Section titled “Direction changes the answer”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.
-
Open
Assets/Platformer/Behavior/DocumentationMemberNodes.bqbehaviorand select read coin goal. It surfacesLevelRules.coinUnlockThreshold, anint, ascoin_unlock_threshold. -
Select check fall. Its one argument,
playerVerticalPosition, is afloatauthored as the constant-10. -
Switch that argument’s source to Blackboard and pick
coin_unlock_threshold. It binds, becauseintwidens tofloatand each leg is judged on its own. -
Now ask for the refusal. Point read coin goal at
LevelRules.moveSpeed, afloat, while its surfaced value is still anint.
How it decides
Section titled “How it decides”- 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 includingchar, finitefloatanddouble, an enum by member name or by its exact underlying literal, andnullfor 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
Section titled “When it goes wrong”When it goes wrong
| Symptom | Check | Fix |
|---|---|---|
| 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. |
- Arguments and results: where these rules get applied, row by row.
- Variables and types: choosing the declared type in the first place.
- Entity variables: the carried kinds this table narrows to on the entity path.
- Member nodes and bindings: where these conversions are applied, card by card.