> 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/state.md).

# State and State Asset

Fields of its own for any object or asset, made in the inspector.

Some values belong to one object and have no script to live in: whether a door is locked, how many points a pickup is worth, how fast each copy of a prefab spins. Writing a script with one field for each, just so a binding has something to point at, is a script nobody needed.

A **State** is a component whose fields you make in the Inspector. Each one, a **member**, has a name, a type and a value, and is drawn with the same field Unity gives a script's field of that type. Drag the object into a bind field and its members are there, like the fields of a script.

A **State Asset** is the same thing as an asset: one set of members, shared by every scene, prefab and script that references it.

## Adding one

<table><thead><tr><th width="200">Kind</th><th>How to create it</th></tr></thead><tbody><tr><td><strong>State</strong></td><td><strong>Add Component ▸ Binding System ▸ State</strong>. One per GameObject.</td></tr><tr><td><strong>State Asset</strong></td><td><strong>Assets ▸ Create ▸ Binding System ▸ State Asset</strong>.</td></tr></tbody></table>

Both start empty, with **+ Add Member** at the foot of the Inspector.

## Adding members

Press **+ Add Member**, pick a type, type a name, and press **Add** or Enter. Escape cancels.

* **The type picker** opens on the types a member nearly always is (numbers, text, vectors, colours, curves, GameObject and the common components), with the rest under **In This Project**, **In Unity** and **In .NET**. Types are named as you would write them in C#: `float`, `int`, `string`.
* **A member can hold** anything Unity serializes as a field: numbers, text, enums, vectors, colours, curves, gradients, references to objects and assets, and your own `[Serializable]` classes and structs. The .NET types Unity does not serialize, such as `DateTime`, are not offered, and neither are generic or abstract types.
* **The name** follows the rules of a field name: words typed with spaces are joined, so `max speed` becomes `maxSpeed`, and it is shown the way Unity shows a script's field, as **Max Speed**. Left empty, the member is named after its type. A name already taken gets a number after it.

## Editing members

**Edit Members** turns each row into the member's definition: a handle to drag it by, its name, its type, a tooltip, and **×** to remove it. **Done** goes back to the values. Right-click a value for **Edit Members**, **Move to Group** and **Remove Member**.

* **Changing the type** keeps the value when it converts: a `float` becomes an `int`, an object stays when it is already of the new type.
* **The tooltip** is what hovering the field shows, as `[Tooltip]` does for a script's field. It is also the member's description in the bind path menu.

Members can only be added, renamed, retyped, moved or removed with a single object selected. With several selected, you edit the values of all of them at once, as long as they have the same members.

## Groups

Members can be sorted into groups, the way a script sorts its fields into nested classes.

* **Adding one:** in **Edit Members**, press **+ Add Group** and type its name.
* **Filling it:** drag a member by its handle into the group, out of it, or to another place in it. The **+** on a group's header adds a new member straight into it, and **Move to Group** on a value's right-click menu works without editing at all.
* **Reordering:** drag a group by its handle to move it among the others.
* **Removing one:** **×** on its header. Its members stay, in no group.

Among the values, the members in no group come first and each group follows as a foldout, which remembers whether you left it open. An empty group only shows while editing. In the bind path menu, a group is a submenu holding its members.

{% hint style="success" %}
**Groups never touch a binding.** A binding finds its member by the member's own id, so moving a member between groups, renaming a group or removing one leaves every binding exactly as it was.
{% endhint %}

## Values

Each value is stored as a real serialized value of its type, not as text, which is what makes a State look and behave like a script:

* each member gets Unity's own field for its type, colour pickers, object pickers and foldouts included;
* undo and redo work as for any field;
* on a prefab, the members are the prefab's and every instance keeps its own values, with the usual **override** marks and **Revert**.

## Binding to a member

Drag the object into a bind field, or set it as the source. In the [bind path menu](/binding-system-3/overview/paths.md), the State is listed under **Components** like any other component. Open it and its members are there, each one as a field would be: pick it, or open it to walk into its value, such as the `x` of a vector or the `position` of a Transform.

A State Asset dragged into a bind field is itself the source, and its members are its fields.

The path reads as the member's name alone, **Speed**, as it would for a script's field. Bindings read and write members like any field.

{% hint style="success" %}
**Renaming a member does not break the bindings that use it.** A binding finds a member by an id the member keeps for life, and only falls back to the name when the id is gone. So a member deleted and made again under the same name is found again too.
{% endhint %}

## Which one to use

<table><thead><tr><th width="200"></th><th>Where the value lives</th><th>How a binding reaches it</th></tr></thead><tbody><tr><td><strong>State</strong></td><td>On one object. Each prefab instance holds its own values.</td><td>Through the object, like a field of one of its scripts.</td></tr><tr><td><strong>State Asset</strong></td><td>In one asset, shared by everything that references it.</td><td>Through the asset, dragged into the bind field.</td></tr><tr><td><a href="/binding-system-3/overview/bind-variables.md"><strong>Bind variable</strong></a></td><td>In a scene or a variables asset, under a name.</td><td>By name, from anywhere, with no reference to drag.</td></tr></tbody></table>

## Play mode

A **State** in a scene behaves like the rest of the scene: what the game writes into it is undone when play mode ends.

A **State Asset** behaves like any asset: what the game writes into it while playing in the editor is still there when play mode ends, and is saved with the asset the next time the project is saved. In a build, the values start from what was saved.

## From code

```csharp
using Postica.BindingSystem;

var state = GetComponent<State>();

// Read a member, with a fallback for when there is none
float speed = state.Get("speed", 1f);

// Write one. Every binding reading it follows.
state.Set("speed", speed * 2f);

// Ask first
if (state.TryGet<Transform>("target", out var target))
    transform.LookAt(target);

// Enumerate the members
foreach (var name in state.Names)
    Debug.Log($"{name}: {state.GetMemberType(name).Name}");
```

`StateAsset` has the same methods. A member is named by its field name (`maxSpeed`), not by the label the Inspector shows (**Max Speed**).

* `Set` converts between numbers, so `Set("count", 3.0)` on an `int` member writes `3`. It returns `false` when there is no such member or the value cannot become its type.
* `Get` and `TryGet` do not convert: ask for the type the member holds.
* Members are made in the Inspector. Code reads and writes their values.

## Notes

* A binding to a member that no longer exists, deleted with no other member of the same name to fall back on, reads the default value of its type and writes nowhere.
* `State` is a short name, and a project may well have one of its own. If a script that uses both namespaces reports `State` as an ambiguous reference, write it in full: `Postica.BindingSystem.State`.

## Related pages

* [Bind Variables](/binding-system-3/overview/bind-variables.md): named values, reached by name from anywhere.
* [Paths and Parameters](/binding-system-3/overview/paths.md): how the bind path menu walks into a member's value.
* [Sources](/binding-system-3/overview/sources.md): the object a binding reads from, and the other ways to name one.
