Skip to main content
Property Bindings is a system that connects gameplay values to animation parameters entirely in the editor. Instead of writing custom binding code that reads a value from your character controller and forwards it to a procedural modifier, you assign a binding once in the Inspector and CAS resolves the connection at runtime. This keeps your gameplay components focused on gameplay and your animation components focused on animation, with no coupling code in between.

How Bindings Are Resolved

When you press the + icon to add a new binding, CAS runs the following resolution process:
1

Acquire the GameObject context

CAS calls IBindableContext on the component that owns the binding. This interface returns a reference to the target GameObject — typically your character or player prefab. Components that support bindings implement IBindableContext and provide the reference.
2

Enumerate bindable members

CAS iterates over every component on the context GameObject and looks for public fields, properties, and methods that return the type the binding expects (most commonly float, bool, or Vector3).
3

Build the dropdown

All discovered members are presented in a dropdown menu in the Inspector, formatted as ComponentType / MemberName.
4

Persist the selection

Once you pick a member from the dropdown, CAS stores the component type and member path in the binding. At runtime, CAS uses this stored path to resolve the value without requiring a direct object reference.
Binding resolution only discovers public members. Private and protected fields are intentionally excluded to keep the dropdown focused on the values that are safe to expose from a gameplay component.

Initialization

Property Bindings are not live immediately — you must build them before they can return values. Building compiles the path stored in each binding into a delegate for fast, allocation-free reads at runtime. Build all bindings once when the game starts, typically in Awake or Start on the component that owns them:
Building bindings is relatively expensive. Call Build exactly once per binding per character instance — never inside Update or in response to frequent events.

Creating Safe Copies

When the same binding is used across multiple character instances, each instance must have its own independent copy of the bound property. Call SafeCopy to create a clone of the binding that can be built against a different context without modifying the original:
This pattern is essential for networked characters and any situation where a single prefab is instantiated more than once.

Getting a Value

Call GetValue() on a built BindableProperty<T> to read the current value of the bound member:
Property Bindings include a built-in null check for reference types. If the bound component or any intermediate reference in the resolved path is null at the time of the call, GetValue() returns the default value rather than throwing a NullReferenceException. This makes it safe to call unconditionally in an update loop.

Setting a Default Value

Use SetDefaultValue to control what GetValue() returns when the binding was not initialized successfully or when a required reference is null:
Set a meaningful default before calling Build so that animation parameters behave correctly even on the first frame before the character controller has fully initialised.
A good rule of thumb: set the default to the value that produces the most neutral or safe animation pose. For a weight binding, 0 usually means “disabled,” which is a safe fallback. For a speed binding, 0 means idle, which is also safe.

Updating the Context at Runtime

When a binding is built, CAS internally creates a delegate that accepts a MonoBehaviour reference as its target. You can replace that target at runtime without rebuilding the binding by calling SetContext:
This is useful when you want to redirect a binding to a different character (for example, when switching camera targets in a spectator system) without paying the cost of rebuilding the binding from scratch.
SetContext is far cheaper than calling Build again. Use it whenever you need to retarget a binding to a new instance of the same component type without changing which field or property is being read.