> For the complete documentation index, see [llms.txt](https://postica.gitbook.io/binding-system-3/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://postica.gitbook.io/binding-system-3/overview/code.md).

# Binding from Code

Reading, writing, creating and rewiring bindings from C#.

This page is about the code half of the system: `Bind<T>` and its family. Everything the Inspector does to a bind field is available from C# as well, which matters for spawned objects, for tests, and for tools.

{% hint style="success" %}
**Learn by doing:** [When to Declare a Bind Field](/binding-system-3/tutorials/bind-field.md) builds the same value two ways and makes the timing difference visible.
{% endhint %}

{% hint style="info" %}
Most bindings do not need any of this. Binding a field from the Inspector as a [proxy binding](/binding-system-3/overview/proxy-bindings.md) requires no code and works on components and assets you cannot edit. Declare a `Bind<T>` when your own code should decide exactly when a value moves. See [Two Ways to Bind](/binding-system-3/overview/two-ways-to-bind.md).
{% endhint %}

{% hint style="info" %}
A `Bind<T>` field is updated by your code reading it, not by the engine, so none of the [update points](/binding-system-3/overview/modes-and-updates.md) apply here. The one automatic option is `BindFlags.AutoUpdate`, a fixed once-per-frame refresh. If you want a value moved on a specific player-loop stage without your code touching it, that is a [proxy binding](/binding-system-3/overview/proxy-bindings.md). See [Two Ways to Bind](/binding-system-3/overview/two-ways-to-bind.md).
{% endhint %}

## Reading and writing

```csharp
public Bind<float> speed;

void Update()
{
    float a = speed;         // implicit conversion
    float b = speed.Value;   // the same thing, explicit

    speed.Value = 42f;       // writes through the pipeline, if the mode allows it
}
```

<table><thead><tr><th width="290">Member</th><th>What it does</th></tr></thead><tbody><tr><td><code>Value</code></td><td>The effective value. Reads through the pipeline when bound, returns the plain value when not.</td></tr><tr><td><code>UnboundValue</code></td><td>The plain serialized value, whether or not the field is bound. Useful as a fallback.</td></tr><tr><td><code>IsBound</code></td><td>Whether this field is driven from somewhere.</td></tr><tr><td><code>CanRead</code>, <code>CanWrite</code></td><td>What the current mode and the target member actually allow.</td></tr><tr><td><code>Source</code></td><td>The resolved source object, or null.</td></tr><tr><td><code>BindData</code></td><td>The bind data, or null when the field is not bound.</td></tr><tr><td><code>Accessor</code></td><td>The compiled accessor. For advanced use.</td></tr><tr><td><code>ValueChanged</code></td><td>The change event. See <a href="/binding-system-3/overview/bind-types.md#noticing-a-change">Bind Types</a>.</td></tr><tr><td><code>Refresh()</code></td><td>Forces this binding to re-evaluate now.</td></tr><tr><td><code>Dispose()</code></td><td>Unregisters the binding from the engine. Called for you in normal Unity lifetimes.</td></tr></tbody></table>

{% hint style="warning" %}
Writing to a `Bind<T>` whose mode is `Read` throws, and so does reading one whose mode is `Write` and whose target cannot be read. That is deliberate: a silent no-op would be much harder to find. Check `CanRead` and `CanWrite` if the mode is not under your control.
{% endhint %}

## Creating a binding at runtime

```csharp
void Start()
{
    var target = GameObject.Find("Sphere").transform;

    // source + path
    speed = new Bind<float>(target, "position.x");

    // with parameters for a method or indexer path
    child = new Bind<Transform>(target, "GetChild(Int32)", 1);
}
```

The constructor takes the source, the path and any parameters. Everything else, mode, converters, modifiers and flags, comes from the bind data:

```csharp
var data = new BindData(target, "position.x", null, -1);

data.SourceContext = transform;
data.TryEnableFlag(BindFlags.AutoUpdate, true);      // refresh once per frame
data.TryEnableFlag(BindFlags.OptimizeUpdate, true);  // only when the value changed
```

| On `BindData`                                                  | What it does                                                                                                                                   |
| -------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `Source`                                                       | Set it to a direct reference. Assigning it also resets the source mode to **Value**.                                                           |
| `SourceContext`                                                | The object the context and search modes resolve from.                                                                                          |
| `Path`                                                         | The path string.                                                                                                                               |
| `Mode`                                                         | Read, write or both.                                                                                                                           |
| `Flags`, `Flags2`                                              | Read-only. Change them with `TryEnableFlag`. The `UpdateOn…` flags are read by `BindProxy` only, so setting them on a `Bind<T>` has no effect. |
| `TryEnableFlag(flag, enable)`                                  | Sets or clears one flag. Returns whether anything changed.                                                                                     |
| `HasFlags(flags)`                                              | Tests a combination.                                                                                                                           |
| `IsValid`                                                      | Whether this data describes something resolvable.                                                                                              |
| `ReadConverter`, `WriteConverter`, `Modifiers`, `PreModifiers` | The pipeline, read-only from here. Build it through the constructor or the Inspector.                                                          |

## Accessors without a bind field

If all you want is fast access to a member by path, the accessor layer is public:

```csharp
using Postica.BindingSystem.Accessors;

var accessor = AccessorsFactory.GetAccessor<float>(transform, "position.x");
float x = accessor.GetValue(transform);
accessor.SetValue(transform, 5f);
```

Accessors are cached per `(type, path)`, so building one twice costs one dictionary lookup. This is the same layer `Bind<T>` uses, which means it benefits from the same [generated accessors](/binding-system-3/project-tools/performance/optimized-accessors.md) at build time.

There is also a typed delegate form for the hot loop:

```csharp
var getX = AccessorsFactory.ValueGetter<Transform, float>("position.x");
float x = getX(transform);
```

## Formatting

Bind types implement `IFormattable`, and there is a helper for logging a binding without resolving it:

```csharp
Debug.Log(speed.ToString("F2", null));          // formats the value
Debug.Log(speed.ToString("speed"));             // prints "speed" if bound, the value if not
```

The second form is what the built-in modifiers use to describe themselves in the Inspector, and it is handy in your own modifiers.

## System information

```csharp
using Postica.BindingSystem;

BindSystem.Version;          // "3.0.0"
BindSystem.ProductName;      // "Binding System"
BindSystem.FullProductText;  // "Binding System v3.0.0"
BindSystem.IsARM64Architecture;
```

{% hint style="info" %}
The two project-wide options, [phased bindings](/binding-system-3/project-tools/performance/phased-bindings.md) and [universal bind control](/binding-system-3/overview/runtime-control.md#who-is-allowed), are package-internal state. Change them in [Project Settings ▸ Binding System ▸ Optimization](/binding-system-3/reference/settings.md#optimization), not from your own code.
{% endhint %}

## Related pages

* [Two Ways to Bind](/binding-system-3/overview/two-ways-to-bind.md): when to reach for code and when not to.
* [Controlling Bindings at Runtime](/binding-system-3/overview/runtime-control.md): pause, resume and refresh.
* [Field Rerouting](/binding-system-3/reference/extending/field-rerouting.md): redirecting a bound field to another member globally.
* [API Cheat Sheet](/binding-system-3/reference/api.md): the whole public surface on one page.
