## Install

Add **Udonite Binding** from the listing. It brings [Udonite](/docs/compiler) and [Observables](/docs/observables) with it.

Then, in a script:

```csharp
using Udonite.Binding;
```

## Hear a control

Three lines: a field to hold the binding, a `Watch` to start it, a `Poll` to keep it going.

```csharp
public class Lights : UdoniteBehaviour
{
    public Toggle box;
    public GameObject lamp;

    private ToggleBinding switched = new ToggleBinding();

    public override void Start()
    {
        switched.Watch(box);
        switched.OnChanged += Flip;
    }

    public override void Update()
    {
        switched.Poll();
    }

    private void Flip(bool on)
    {
        lamp.SetActive(on);
    }
}
```

**The binding is a field, not a local.** It holds the handler, so it has to outlive the method that made it. A local goes out of scope and the control quietly stops working.

**`Poll()` belongs in `Update`.** It is one comparison a frame. Leave it out for a control the player cannot touch, and nothing will be reported.

## Show a value

The other half needs no polling. Give a binding an [Observable](/docs/observables) and it writes the control whenever the value changes:

```csharp
private Observable<int> score = new Observable<int>();

private TextBinding<int> scoreText = new TextBinding<int>();

public override void Start()
{
    scoreText.Bind(label, score, "Score: ", "");
}

public void Goal()
{
    score.Value = score.Value + 1;      // the label updates itself
}
```

The label shows the value **at bind time**, not at the next change, so a scoreboard does not sit blank until somebody scores.

## Both at once

`Bind` on a watched control does both: the player moves it and the value follows, code changes the value and the control follows.

```csharp
private Observable<float> volume = new Observable<float>(0.5f);

private SliderBinding slider = new SliderBinding();

public override void Start()
{
    slider.Bind(volumeSlider, volume);
}

public override void Update()
{
    slider.Poll();
}
```

They do not chase each other. An observable only notifies when its value actually differs, so the write the binding makes in response to its own poll changes nothing and stops there.

**Only the player's changes raise `OnChanged`.** Moving the control by assigning the observable does not, because the code that assigned it already knows.

## A handler on another behaviour

A handler does not have to live where the binding does:

```csharp
public Scoreboard display;

volume.OnChanged += display.Show;
```

That reaches the other behaviour's `Show` when the player moves the control. It needs no inspector wiring either, and the method name is one the compiler checks.

## Common mistakes

**A local instead of a field.** The commonest one. `Watch` returns nothing and the control simply never reports.

**Forgetting `Poll()`.** The bind half still works — the control follows the value — so it looks half-broken rather than unwired.

**Binding in a `Start` that runs twice.** Harmless: binding again replaces the previous binding rather than adding to it, so you get one, not two.

**Expecting a button.** There is no `ButtonBinding`, and there cannot be one. See [the reference](/docs/binding/reference) for why.
