# Variables

!!! note "Summary"
    A **Variable** stores typed values between Events. Use a Local Variable for state owned by one game object and a Global Variable for state shared across the game.

![A Global Variable asset with no values](assets/global-variables.jpg)

## Two containers, one interface

Visual Script has two kinds of variable container. Both expose the same read and write operations, but they differ in scope, lifetime, and setup:

| Property | **Local Variable** | **Global Variable** |
| :--- | :--- | :--- |
| **Is a** | Component on a game object | Asset in the project |
| **Scope** | That object only | The whole game |
| **Copies** | One per instance | Exactly one |
| **Lives in** | The scene | The project |
| **Created with** | `Add Component` | `Create` &rarr; `Visual Script` &rarr; `Variable` |

An Instruction that writes a number uses the same Signals for either container.

![A Local Variable component with no values](assets/local-variables.jpg)

## Choosing between them

Use a Local Variable when a value belongs to a specific object, such as an enemy's health, a door's locked state, or a chest's contents. Each prefab instance then receives an independent copy.

!!! example "Local state keeps enemy health independent"
    Add a **Local Variable** component with a `health` entry to the enemy prefab, then spawn several enemies. Each instance has its own health, so damaging one doesn't change the others' values. You don't need to configure each instance separately.

Use a Global Variable for state shared across the game, such as the score, difficulty, or whether the tutorial was completed.

!!! tip "Default to local state"
    Project-wide variables are accessible from any system, which makes unexpected writes harder to trace. Use one only when several unrelated systems need the same value.

## Anatomy

Both containers hold an ordered list of **entries**, and each entry has exactly two fields:

| Field | Is |
| :--- | :--- |
| **Tag** | An optional label. Signals use it to pick this entry out of the list. |
| **Value** | The data itself, of a type you choose. |

The available types are the same ones Signals use: **Number**, **String**, **Bool**, **Vector2**, **Vector3**, **Quaternion**, **Color**, **Game Object**, **Sprite**, **Texture**, **Material**, **Animation Clip**, **Audio Resource**, and **Scriptable Object**.

![An entry with a tag and a numeric value](assets/variable-player-health.jpg)

## Tags are optional

Tag an entry when it represents specific state, such as `player-health` or `is-door-open`. You can leave the tag empty for an item in a sequence, where Signals select entries by position. See [Variables as lists](lists.md).

Tags follow two matching rules:

* **They're normalized.** Letters, digits, `-`, and `_` stay as entered; all other characters, including spaces, become `-`. Enter `player health` and the tag becomes `player-health`.
* **They're case-sensitive, and duplicates are allowed.** `Player-Health` and `player-health` are different tags. If two entries share a tag, a lookup by tag finds the first match.

Choose tags that describe the state they hold. For example, `player-health` makes the entry's purpose clearer than `hp2`.

## Reading and writing

Events read and write variables through [Signals](../signals/index.md):

* **Reading** — set any Get Signal's source to **Variable**, choose the container, then choose how to pick the entry inside it.
* **Writing** — use a **Set** Instruction whose Set Signal points at the variable.

Every variable Signal has those two halves: *which container* and *which entry*. The **Index** dropdown selects the entry and defaults to **First**.

Keep that default for a container with one value; select another option once it holds several. [Variables as lists](lists.md) covers the remaining options.

!!! example "A counter reads and writes one variable"
    1. Add a **Local Variable** component with a number entry tagged `counter`.
    2. Add an **Event** with an **On Mouse Down** Trigger.
    3. Add a **Set Number** Instruction: set `counter` to `counter + 1`.

    Both halves of the last step are Signals. The left one points at the variable to write; the right one adds `1` to that variable's current value. The Instruction reads the value before writing the result, so `counter` increases by `1` on each click.

    **Increment Number** performs the same update in one Instruction. The expanded form exposes the separate read and write Signals.

Signals handle supported type conversions. For example, you can read a Number entry into an Integer field without adding a conversion step.

!!! warning "Writing the wrong type rewrites the entry"
    An entry's type isn't fixed. Writing a String Signal into an entry that held a Number changes the entry into a String; the write is neither converted nor rejected.

    Later Number reads parse numeric text and return `0` for other text, so the mistake usually appears as a wrong value instead of an error. The authored type returns when Play mode ends.

## Reacting to changes

Variables support change notification, so **On Number Change** and its siblings work on them directly.

Use a separate Event to watch a value instead of updating every consumer from the Event that changed it. The score logic then has no dependency on its label, and another reaction can subscribe independently. See [Bindings](../signals/bindings.md).

## Inspecting at runtime

Select the object or asset during Play mode and the Inspector shows live values as they change. Use them to verify which Event changed an entry and what it contains now.

![A Variable value at runtime](assets/variable-runtime.jpg)

Each row is shown as its index, its tag if it has one, and its current value.

!!! info "Runtime values don't persist"
    Both kinds work on a copy of the values you authored. Runtime writes don't change the asset, prefab, or scene file, and the values revert when Play mode ends. To keep values between sessions, use the [save system](../save-load/index.md).

## Try it

* Build the click counter above and watch the number climb in the Inspector.
* Duplicate the object. Because the state is local, each copy counts independently.
* Swap the Local Variable for a Global Variable and watch both copies share one counter.
* Add an **On Number Change** Trigger watching `counter` and log a message when it changes.
* Open the **Count Clicks** [example scene](../installation.md#installing-the-examples), which builds a counter along these lines.

## Where to go next

<div class="grid cards" markdown>

- **[Local Variables](local-variables.md)** — store state on one game object or prefab instance.
- **[Global Variables](global-variables.md)** — register state shared across the project.
- **[Variables as lists](lists.md)** — select entries by tag or position and change list shape.

</div>
