# State Designer - Opsive Documentation

> Complete State Designer documentation, generated from the Opsive documentation source on 2026-08-14.

Documentation home: https://opsive.com/support/documentation/state-designer/

## Contents

- [State Designer](#page-state-designer)
  - [Overview](#page-state-designer-overview)
  - [Requirements](#page-state-designer-requirements)
  - [Getting Started](#page-state-designer-getting-started)
    - [Your First State Machine](#page-state-designer-getting-started-first-state-machine)
    - [Sample Scenes](#page-state-designer-getting-started-sample-scenes)
  - [Concepts](#page-state-designer-concepts)
    - [What is a Finite State Machine?](#page-state-designer-concepts-what-is-a-finite-state-machine)
    - [Finite State Machines vs Behavior Trees](#page-state-designer-concepts-finite-state-machines-vs-behavior-trees)
    - [Blackboard](#page-state-designer-concepts-blackboard)
    - [States](#page-state-designer-concepts-states)
      - [Action State](#page-state-designer-concepts-states-action-state)
      - [Any](#page-state-designer-concepts-states-any)
      - [Subgraph Reference](#page-state-designer-concepts-states-subgraph-reference)
    - [Actions](#page-state-designer-concepts-actions)
      - [Built-in Actions](#page-state-designer-concepts-actions-built-in-actions)
    - [Conditions](#page-state-designer-concepts-conditions)
      - [Built-in Conditions](#page-state-designer-concepts-conditions-built-in-conditions)
    - [Transition Evaluation and Priority](#page-state-designer-concepts-transition-evaluation-and-priority)
    - [Common Graphs](#page-state-designer-concepts-common-graphs)
      - [Patrol, Chase, and Attack](#page-state-designer-concepts-common-graphs-patrol-chase-and-attack)
      - [Flee at Low Health](#page-state-designer-concepts-common-graphs-flee-at-low-health)
      - [Attack with Cooldown](#page-state-designer-concepts-common-graphs-attack-with-cooldown)
      - [Timed State Cycle](#page-state-designer-concepts-common-graphs-timed-state-cycle)
      - [React to an Event](#page-state-designer-concepts-common-graphs-react-to-an-event)
      - [Toggle an Interaction](#page-state-designer-concepts-common-graphs-toggle-an-interaction)
      - [Reusable Attack Subgraph](#page-state-designer-concepts-common-graphs-select-a-reusable-attack-subgraph)
      - [Menu Screen Flow](#page-state-designer-concepts-common-graphs-menu-screen-flow)
      - [Dialogue Choice Flow](#page-state-designer-concepts-common-graphs-dialogue-choice-flow)
      - [Turn-Based Phase Loop](#page-state-designer-concepts-common-graphs-turn-based-phase-loop)
      - [Save and Resume a State Machine](#page-state-designer-concepts-common-graphs-save-and-resume-a-state-machine)
      - [Persistent State Across Scenes](#page-state-designer-concepts-common-graphs-persistent-state-across-scenes)
      - [Animation-Driven Locomotion](#page-state-designer-concepts-common-graphs-animation-driven-locomotion)
  - [New Nodes](#page-state-designer-new-nodes)
    - [GameObject Action](#page-state-designer-new-nodes-gameobject-action)
    - [GameObject Condition](#page-state-designer-new-nodes-gameobject-condition)
    - [Entity Action](#page-state-designer-new-nodes-entity-action)
    - [Entity Condition](#page-state-designer-new-nodes-entity-condition)
  - [Variables](#page-state-designer-variables)
    - [Accessing Variables](#page-state-designer-variables-accessing-variables)
    - [Scope](#page-state-designer-variables-scope)
    - [Property Binding](#page-state-designer-variables-property-binding)
    - [Entity Variables](#page-state-designer-variables-entity)
  - [Entity Baking](#page-state-designer-entity-baking)
  - [Events](#page-state-designer-events)
  - [Subgraphs](#page-state-designer-subgraphs)
  - [Debugging](#page-state-designer-debugging)
  - [Referencing Scene Objects](#page-state-designer-referencing-scene-objects)
  - [Save/Load](#page-state-designer-save-load)
  - [Extending the Editor](#page-state-designer-extending-the-editor)
    - [Control Types](#page-state-designer-extending-the-editor-control-types)
    - [Node Views](#page-state-designer-extending-the-editor-node-views)
  - [API](#page-state-designer-api)
  - [Networking](#page-state-designer-networking)
  - [Integrations](#page-state-designer-integrations)
    - [Animal Controller](#page-state-designer-integrations-animal-controller)
    - [Atlas](#page-state-designer-integrations-atlas)
    - [Behavior Designer Pro](#page-state-designer-integrations-behavior-designer-pro)
    - [Curvy Splines](#page-state-designer-integrations-curvy-splines)
    - [Dialogue System](#page-state-designer-integrations-dialogue-system)
    - [DOTS Survivors](#page-state-designer-integrations-dots-survivors)
    - [Essential Kit](#page-state-designer-integrations-essential-kit)
    - [Feel](#page-state-designer-integrations-feel)
    - [Juicy Actions](#page-state-designer-integrations-juicy-actions)
    - [Love/Hate](#page-state-designer-integrations-love-hate)
    - [PlayMaker](#page-state-designer-integrations-playmaker)
    - [Quest Machine](#page-state-designer-integrations-quest-machine)
    - [Sensor Toolkit 2](#page-state-designer-integrations-sensor-toolkit-2)
    - [Simple Waypoint System](#page-state-designer-integrations-simple-waypoint-system)
    - [Ultimate Character Controller](#page-state-designer-integrations-ultimate-character-controller)
    - [Ultimate Inventory System](#page-state-designer-integrations-ultimate-inventory-system)

---

<a id="page-state-designer"></a>

# State Designer

[View this page online](https://opsive.com/support/documentation/state-designer/)

State Designer is a visual finite state machine editor for Unity. It helps teams organize gameplay into clear modes, connect those modes with explicit transitions, and inspect the active flow in Play Mode.

Use it when behavior is easiest to understand as states such as Idle, Patrol, Chase, or Attack. The documentation is organized for both editor-focused authors building graphs and developers adding project-specific logic or integrations.

## Start here

1. Check the [Requirements](https://opsive.com/support/documentation/state-designer/requirements/) before importing or upgrading the package.
2. Follow [Getting Started](https://opsive.com/support/documentation/state-designer/getting-started/) to import a sample and create a first graph.
3. Build [Your First State Machine](https://opsive.com/support/documentation/state-designer/getting-started/first-state-machine/) and verify the active-state loop in Play Mode.
4. Choose the next working example from [Sample Scenes](https://opsive.com/support/documentation/state-designer/getting-started/sample-scenes/).
5. Work through the [Overview](https://opsive.com/support/documentation/state-designer/overview/) for the complete editor workflow with states, transitions, and runtime inspection.
6. Read [What is a Finite State Machine?](https://opsive.com/support/documentation/state-designer/concepts/what-is-a-finite-state-machine/) when the state-machine model is new to you.

## Build a state machine

- [Concepts](https://opsive.com/support/documentation/state-designer/concepts/) introduces states, Actions, Conditions, transitions, and the blackboard.
- [Transition Evaluation and Priority](https://opsive.com/support/documentation/state-designer/concepts/transition-evaluation-and-priority/) explains competing transitions, evaluation timing, Any, and re-entry.
- [Common Graphs](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/) combines those pieces into practical flows for AI, interactions, cooldowns, events, reusable attacks, and menus.
- [Built-in Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/built-in-actions/) and [Built-in Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/built-in-conditions/) are nested beneath their owning concept pages.
- [Variables](https://opsive.com/support/documentation/state-designer/variables/) covers shared values, scope, access, property binding, and Entity variables.
- [Events](https://opsive.com/support/documentation/state-designer/events/) shows how a graph or script can notify a state machine.
- [Subgraphs](https://opsive.com/support/documentation/state-designer/subgraphs/) explains how to reuse part of a state machine in another graph.
- [Debugging](https://opsive.com/support/documentation/state-designer/debugging/) starts with the Error Window, then provides a symptom-to-check-to-fix route through the active State, transition order, and Shared Variables.

## Choose a runtime workflow

Use GameObject Actions and Conditions for most behavior that works with scene objects and existing Unity components. Start with the [New Nodes](https://opsive.com/support/documentation/state-designer/new-nodes/) guide when built-in behavior does not cover the project's needs.

Choose the Entity workflow when the project already uses ECS or profiling shows that the behavior should run across many entities. [Entity Baking](https://opsive.com/support/documentation/state-designer/entity-baking/) covers the prefab and runtime setup. The Entities package is required by State Designer even when all custom behavior uses the GameObject workflow; see [Requirements](https://opsive.com/support/documentation/state-designer/requirements/) for the supported versions and platforms.

## Connect State Designer to the project

- [Referencing Scene Objects](https://opsive.com/support/documentation/state-designer/referencing-scene-objects/) covers safe ways to supply scene references to graphs and Subgraphs.
- [Save and Load](https://opsive.com/support/documentation/state-designer/save-load/) covers preserving state-machine and variable data.
- [Networking](https://opsive.com/support/documentation/state-designer/networking/) explains how to run decisions on the authoritative instance and synchronize their results through the project's networking layer.
- [Integrations](https://opsive.com/support/documentation/state-designer/integrations/) connects State Designer to Atlas, other Opsive products, movement and sensing tools, dialogue and quest systems, feedback, visual scripting, and platform services.

## Extend and reference

- [Extending the Editor](https://opsive.com/support/documentation/state-designer/extending-the-editor/) introduces custom Inspector controls and node views.
- [API](https://opsive.com/support/documentation/state-designer/api/) lists the `StateMachine` methods and events used by scripts.

---

<a id="page-state-designer-overview"></a>

# Overview

[View this page online](https://opsive.com/support/documentation/state-designer/overview/)

<iframe width="100%" height="600" src="https://www.youtube.com/embed/V5i1emk58Gc?rel=0&amp;showinfo=0" title="State Designer overview video" loading="lazy" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>

If the embedded player is unavailable, [watch the State Designer Overview on YouTube](https://www.youtube.com/watch?v=V5i1emk58Gc).

State Designer is a visual finite state machine editor for Unity. Use it when gameplay is easiest to understand as distinct modes, such as Idle, Patrol, and Attack, with explicit transitions between them. This structure works well for gameplay flow, boss phases, animation control, and mode switching.

If finite state machines are new to you, start with [What is a Finite State Machine?](https://opsive.com/support/documentation/state-designer/concepts/what-is-a-finite-state-machine/) for an introduction to states, transitions, and conditions.

## In the editor

Open **Tools > Opsive > State Designer > Editor**.

![The State Designer window before a GameObject and state machine graph are selected.](https://opsive.com/wp-content/uploads/2026/02/BehaviorDesignerProEmptyEditor-1024x502.png)

The editor has four main areas:

![The State Designer editor labeled with the graph, Element Inspector, operations toolbar, and debug toolbar.](https://opsive.com/wp-content/uploads/2026/02/BehaviorDesignerProEmptyEditorLabels-1024x502.png)

1. The graph is where you create and arrange states and transitions.
2. The Element Inspector and Shared Variables panel are where you configure the selected element and reusable values.
3. The operations toolbar selects and manages state machine graphs.
4. The debug toolbar controls runtime inspection.

To create a graph, add a State Machine component by right-clicking the graph and selecting **Add State Machine**, or use the add button in the operations toolbar. Press Space or right-click the graph and select **Create State** to add the first state.

![The Create State menu listing the state types available in State Designer.](https://opsive.com/wp-content/uploads/2026/02/AddStateFilterWindow.png?v=4fca079c9ff9)

Adding the first state also adds the Start event, which provides the entry point into the graph.

![A new Idle state connected to the Start event in a State Designer graph.](https://opsive.com/wp-content/uploads/2026/03/AddIdleNode.png?v=420b226b6b96)

Add Patrol and Log, then drag between their connection points to create transitions from Idle to Patrol, Patrol to Log, and Log back to Idle. Select a connection and press Delete if you need to remove it; drag a state to rearrange the graph.

![Idle, Patrol, and Log states connected in a loop.](https://opsive.com/wp-content/uploads/2026/03/IdlePatrolLog.png?v=bc2449f52ae1)

Select a transition to configure its conditions in the Element Inspector. New transitions use **State Finished** by default. For this example, replace the Idle-to-Patrol condition with **Timer** and set the duration.

![The Element Inspector configuring a Timer condition for a transition.](https://opsive.com/wp-content/uploads/2026/02/TimerElementInspector.png?v=718045b49548)

Select a state to rename it, add a comment, or edit its serialized fields. The Log state in this example exposes a **Text** field that can use either a direct value or a Shared Variable.

![The Log state selected with its Text field visible in the Element Inspector.](https://opsive.com/wp-content/uploads/2026/03/LogInspector.png?v=46afaed1ee42)

## How it runs

The Start event enters Idle. After the Timer duration, the state machine transitions to Patrol. Because Patrol does not finish on its own in this example, an **Is Mouse Button Down** condition moves it to Log. Log finishes its work, and the default **State Finished** condition returns the state machine to Idle.

The resulting flow is Idle → Patrol → Log → Idle. Actions perform the work inside a state, while conditions decide when an outgoing transition is allowed to run. During Play mode, the editor shows the active state so you can follow this flow as it executes.

## Important editor controls

![The State Designer operations toolbar with navigation, graph selection, Export, Find, and lock controls.](https://opsive.com/wp-content/uploads/2026/02/BehaviorDesignerOverviewOperationsToolbar-1024x48.png)

Use the operations toolbar to move backward or forward through recently opened graphs, choose a GameObject and one of its state machines, export the current graph as a Subgraph, search with Find, or lock the current graph while selecting other Unity objects.

**Export** copies the complete graph into a Subgraph asset without changing the source graph. To extract and replace a selected region, use **Save as Subgraph** as described on the [Subgraphs](https://opsive.com/support/documentation/state-designer/subgraphs/) page. The bottom status bar provides play, pause, and available step controls for runtime inspection; its error count opens the Error Window.

Choose the narrowest Shared Variable scope that needs the value: Graph for one graph, GameObject for state machines on one object, Scene for the current scene, or Project for the entire project. See [Variable Scope](https://opsive.com/support/documentation/state-designer/variables/scope/) for the differences.

### Use the graph background menu

Right-click empty graph space to use the following graph-level commands:

| Command | Result |
| --- | --- |
| **Create State** | Opens the State selector at the pointer. Space performs the same action. |
| **Create Group** | Creates an organizational group around the current selection when applicable. |
| **Paste** | Pastes compatible graph elements from the clipboard. |
| **Frame Selection / Frame All** | Fits the selected elements or complete graph in the window. |
| **Focus > Selection Only / Connected Neighborhood / Off** | Dims unrelated elements without changing runtime behavior. |
| **Add State Machine** | Adds another State Machine component to the selected GameObject. |
| **Remove State Machine** | Removes the selected component after confirmation. |

State and group commands are documented with [States](https://opsive.com/support/documentation/state-designer/concepts/states/), Action-row commands with [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/), transition and Condition commands with [Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/), and Shared Variable row commands with [Variables](https://opsive.com/support/documentation/state-designer/variables/).

### Arrange the graph

Use the **Panels** menu to show, hide, resize, or rearrange the Element Inspector and Shared Variables panel. **Reset Layout** restores the product layout when a panel is hidden or unusably small. **Frame Selection**, **Frame All**, Connected Neighborhood focus, zoom-aware readability, and the mouse-wheel preference control how the graph is presented without changing the asset.

### Inspect graph errors

Open **Tools > Opsive > State Designer > Error Window**, select the status-bar error count, or press **Ctrl/Cmd+E**. Selecting an error briefly identifies its State in the graph. A clean Error Window means that the editor found no known structural or field errors; it does not replace a Play Mode test.

### Configure preferences

Open **Preferences > State Designer** or **Tools > Opsive > State Designer > Settings**.

| Preference | What it controls |
| --- | --- |
| **Show Hierarchy Icon** | Shows the State Designer indicator in Unity's Hierarchy. |
| **Check For Errors** | Runs editor validation and updates the status-bar error count. |
| **Auto Save Prefab** | Saves prefab graph changes automatically. When off, use **Ctrl/Cmd+S** when prompted. |
| **Keep Graph Selected** | Keeps the current graph when the next Unity selection has no state machine. |
| **Panels** | Chooses the registered panels shown by default. |
| **Mouse Wheel Scrolls Graph** | Uses the wheel to scroll rather than perform the normal graph zoom action. |
| **Keep Selection On Graph Click** | Keeps selected elements when empty graph space is clicked. |
| **Grid Line Spacing / Transparency** | Controls the editor grid interval and opacity. |
| **Focus Mode** | Chooses the default focus view. |
| **Zoom-aware Readability** | Hides secondary detail when zoomed far out. |
| **Recent Entries** | Limits Recent entries in State, Action, and Condition selectors; `0` hides them. |
| **Show Node Icon / Description / Debug Info** | Chooses the information rendered on State nodes. |
| **Snap To Grid** | Aligns moved States to the editor grid. |
| **Default Gizmos Color** | Sets the default Scene-view gizmo color. |

These settings affect authoring and presentation rather than State, Action, or Condition logic unless the setting explicitly controls saving or serialization.

### Use keyboard shortcuts

Open Unity's Shortcut Manager or select **Edit Bindings** in the shortcut preferences to rebind these defaults:

| Shortcut | Action |
| --- | --- |
| Space | Create State |
| Ctrl/Cmd+F | Open Find |
| Ctrl/Cmd+Shift+F | Focus the next Find result |
| Ctrl/Cmd+G | Create a group from the selection |
| Ctrl/Cmd+Shift+G | Remove selected groups without deleting their States |
| Home | Focus the initial node |
| F / A | Frame Selection / Frame All |
| Shift+F | Toggle Connected Neighborhood focus |
| Ctrl/Cmd+0 | Reset zoom |
| C | Collapse or expand the selection |
| Enter | Focus the Element Inspector |
| Arrow keys / Shift+Arrow keys | Nudge by the normal or larger step |
| Ctrl/Cmd+E | Open the Error Window |
| Esc | Cancel the active operation or clear the applicable selection |

Standard Cut, Copy, Paste, Duplicate, Delete, and Save shortcuts apply whenever the matching graph command is available. State Designer preferences are also available in the [Unity Preferences window](https://docs.unity3d.com/Manual/Preferences.html).

## Related pages

- [States](https://opsive.com/support/documentation/state-designer/concepts/states/)
- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/) and [Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/)
- [Common Graphs](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/)
- [GameObject Action](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-action/) and [GameObject Condition](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-condition/)
- [Subgraphs](https://opsive.com/support/documentation/state-designer/subgraphs/)

---

<a id="page-state-designer-requirements"></a>

# Requirements

[View this page online](https://opsive.com/support/documentation/state-designer/requirements/)

State Designer uses Unity Entities internally to run state machines efficiently. The Entities package is required even when every state uses the GameObject workflow.

## Compatibility

- **Unity:** Unity 2022.3.11 is the minimum supported version.
- **Entities:** Version 1.3.8 of the [Entities package](https://docs.unity3d.com/Packages/com.unity.entities@1.3/manual/getting-started-installation.html) is required.
- **WebGL:** State Designer does not support WebGL because the required Entities and Burst packages do not currently support it.

## Verify your project

Before creating a state machine, check the following in Unity:

1. Open Package Manager and confirm that Entities 1.3.8 is installed.
2. Import State Designer and confirm that its Welcome Window does not ask you to install Entities.
3. Confirm that the project is using Unity 2022.3.11 or newer.
4. Use a build target other than WebGL.

## Next steps

- Follow [Getting Started](https://opsive.com/support/documentation/state-designer/getting-started/) to import the samples and open the editor.
- Read the [Overview](https://opsive.com/support/documentation/state-designer/overview/) to create a first state machine.
- See [Entity Baking](https://opsive.com/support/documentation/state-designer/entity-baking/) when using the Entity workflow.

---

<a id="page-state-designer-getting-started"></a>

# Getting Started

[View this page online](https://opsive.com/support/documentation/state-designer/getting-started/)

Use this page to explore the State Designer Samples Hub, open a working sample, and create the first states in your own graph. By the end, you will be able to follow the active state in Play Mode.

## Before you begin

Confirm that your project meets the [State Designer requirements](https://opsive.com/support/documentation/state-designer/requirements/) before importing sample content or creating a graph.

If state machines are new to you, read [What is a Finite State Machine?](https://opsive.com/support/documentation/state-designer/concepts/what-is-a-finite-state-machine/) for a short explanation of states and transitions.

## Explore the Samples Hub

Open **Tools > Opsive > State Designer > Samples**. The Samples Hub lists 15 sample-scene cards even before the project-local sample content has been imported. The screenshot shows the post-import state, with the import notice hidden and the available **Open Scene** actions enabled.

![The State Designer Samples Hub lists imported sample cards with preview images, dependency status, and enabled Open Scene buttons.](https://opsive.com/wp-content/uploads/2026/08/state-designer-getting-started-sample-hub.webp?v=ae3e7bbf7f98)

Each card includes:

- A preview image and a description of the behavior demonstrated by the scene.
- A **Beginner**, **Intermediate**, or **Advanced** difficulty badge and topic badges such as Events, UI, Subgraphs, Physics, or DOTS.
- Dependency indicators. A check mark means the package is installed; an exclamation mark identifies a required package that is missing.
- **Open Documentation** when that sample has a related guide. This opens the guide in the web browser.
- **Open Scene** when Unity can resolve the sample scene in the project.

## Import or update the samples

1. Select **Import Samples** when the sample content has not been imported. State Designer creates a project-local copy through Unity's Package Manager sample workflow.
2. If content from an earlier State Designer version is present, select **Update Samples** to import the current package's sample content. The older versioned folder may remain in the project, but it is no longer the current copy.
3. Check the dependency indicators on the card you want to use and install any required packages that are marked with an exclamation point.
4. Select **Open Documentation** first when the card provides it, then select **Open Scene**. If the current scene has unsaved changes, Unity asks whether to save them before opening the sample.
5. Enter Play Mode and watch the active state change as the sample's transition Conditions become valid.

After the current sample content is installed, the import notice is hidden. Reopen **Tools > Opsive > State Designer > Samples** whenever you want to compare the cards or open another available scene.

## Create your first graph

1. Open **Tools > Opsive > State Designer > Editor**.
2. In the graph area, right-click and select **Add State Machine**, or use the add button in the operations toolbar.
3. Press the Space bar or right-click the graph and select **Create State**. Adding the first state also adds the Start event.
4. Add another state, then drag from the first state's connection slot to the second state.
5. Select the transition and choose the Condition that should move execution to the next state.
6. Enter Play Mode to test the graph.

New transitions use **State Finished** by default, which waits for the current state to finish. Choose a different Condition when the transition should respond to a timer, input, or another gameplay rule.

For exact state names, Action values, transition settings, screenshots, and a result you can reproduce, continue with [Your First State Machine](https://opsive.com/support/documentation/state-designer/getting-started/first-state-machine/).

## How it runs

The Start event activates the first connected state. The editor highlights the active state in Play Mode; when a transition Condition becomes valid, the state machine leaves that state and activates the next one. If the highlighting follows the order you connected, the graph is running correctly.

The **Tools > Opsive > State Designer** menu also opens **Welcome** for product links, **State Palette** for the dockable State browser, **Error Window** for graph validation, **Atlas** for assisted authoring, and **Integrations** for optional packages. **Settings** opens the product preferences described in the Overview. **Upgrade Project Serialization** is a project-data migration command; back up or commit the project before using it.

## Related pages

- Follow the complete [State Designer overview](https://opsive.com/support/documentation/state-designer/overview/) to build an Idle, Patrol, and Log example.
- Learn how to add gameplay logic with [GameObject Actions](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-action/).
- Learn how transitions make decisions with [GameObject Conditions](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-condition/).
- Share values between nodes with [Variables](https://opsive.com/support/documentation/state-designer/variables/).
- Adapt complete gameplay patterns from [Common Graphs](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/).
- Choose the next imported example from [Sample Scenes](https://opsive.com/support/documentation/state-designer/getting-started/sample-scenes/).
- Diagnose a graph with [Debugging](https://opsive.com/support/documentation/state-designer/debugging/).
- Use the [Overview](https://opsive.com/support/documentation/state-designer/overview/) for graph navigation and layout, then open the [States](https://opsive.com/support/documentation/state-designer/concepts/states/), [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/), [Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/), [Variables](https://opsive.com/support/documentation/state-designer/variables/), or [Subgraphs](https://opsive.com/support/documentation/state-designer/subgraphs/) page for options owned by that feature.

---

<a id="page-state-designer-getting-started-first-state-machine"></a>

# Your First State Machine

[View this page online](https://opsive.com/support/documentation/state-designer/getting-started/first-state-machine/)

Build a three-state loop that waits in Idle, enters Patrol, writes a Console message in Log, and returns to Idle. The graph provides a visible active-state sequence and one controlled value to change.

## Before you begin

- Complete [Getting Started](https://opsive.com/support/documentation/state-designer/getting-started/).
- Confirm the project uses Unity 2022.3.11 or newer and Entities 1.3.8.
- Use a saved scene outside the imported sample folder.

## Create the graph owner

1. Create an empty GameObject and name it `FirstStateMachine`.
2. Open **Tools > Opsive > State Designer > Editor**.
3. Keep `FirstStateMachine` selected.
4. Right-click empty graph space and select **Add State Machine**, or use the operations-toolbar add button.

The editor should show the selected GameObject, its state machine, the Element Inspector, and the Shared Variables panel.

![The State Designer editor is labeled with the graph, Element Inspector, operations toolbar, and debug toolbar.](https://opsive.com/wp-content/uploads/2026/02/BehaviorDesignerProEmptyEditorLabels-1024x502.png)

## Add the states

1. Press **Space** and add an **Idle** state.
2. Add an **Action State**, rename it `Patrol`, and add a **Wait** Action with a duration of `1` second.
3. Add another **Action State**, rename it `Log`, and add a **Log** Action with the text `State machine cycle complete`.
4. Connect Start to Idle.
5. Connect Idle to Patrol, Patrol to Log, and Log back to Idle.

The resulting graph forms a left-to-right flow with a return transition below it.

![Idle, Patrol, and Log states form a repeating State Designer loop.](https://opsive.com/wp-content/uploads/2026/03/IdlePatrolLog.png?v=bc2449f52ae1)

## Configure the transitions

1. Select the Idle-to-Patrol transition.
2. Replace **State Finished** with **Timer** and set its duration to `1` second.
3. Keep Patrol-to-Log and Log-to-Idle on **State Finished**.
4. Open the Error Window and resolve every missing state, transition, or required field.

![The Idle-to-Patrol transition uses a Timer Condition with a configured duration.](https://opsive.com/wp-content/uploads/2026/02/TimerElementInspector.png?v=718045b49548)

Idle has no Action that finishes, so its Timer transition provides the exit. Patrol finishes after Wait. Log writes the message and finishes immediately, allowing its default State Finished transition to return to Idle.

## Verify in Play Mode

1. Clear the Unity Console and enter Play Mode.
2. Watch Idle become active for one second.
3. Watch Patrol remain active while its Wait Action runs.
4. Confirm that Log activates, the Console prints `State machine cycle complete`, and the graph returns to Idle.
5. Observe at least two complete cycles.

![The Log state exposes the Text field used for the tutorial's Console message.](https://opsive.com/wp-content/uploads/2026/03/LogInspector.png?v=46afaed1ee42)

Pause Play Mode while Patrol is active if Log finishes too quickly to see. The active-state highlight and repeated Console message together prove that state entry, Action completion, and transition evaluation are all working.

## Make one controlled change

Change the Idle Timer from one second to three seconds. The state order should stay the same while Idle remains active longer. If another part of the cycle changes, inspect the transition you edited and undo unrelated graph changes.

## Troubleshooting

| Symptom | Check | Fix |
| --- | --- | --- |
| No state becomes active. | Selected owner, enabled State Machine component, Start connection, and Console errors. | Select or enable the correct owner, connect Start to Idle, and resolve compile errors. |
| The graph remains in Idle. | Idle-to-Patrol Timer Condition and Evaluation Mode. | Assign Timer, set a positive duration, and use Continuous evaluation. |
| Patrol never finishes. | Wait duration and Action execution. | Use a finite positive Wait and confirm the Action is enabled. |
| Log never activates. | Patrol-to-Log connection and State Finished Condition. | Restore the transition and its default Condition. |
| The graph loops too quickly. | Timer and Wait values. | Use visible one-second values before tuning the production graph. |

Use [Debugging](https://opsive.com/support/documentation/state-designer/debugging/) when the first invalid state or transition is not clear.

## Continue learning

1. Use [Transition Evaluation and Priority](https://opsive.com/support/documentation/state-designer/concepts/transition-evaluation-and-priority/) before adding competing transitions.
2. Adapt a complete [Common Graph](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/).
3. Use [Shared Variables](https://opsive.com/support/documentation/state-designer/variables/) when Actions and Conditions need the same data.
4. Use [Subgraphs](https://opsive.com/support/documentation/state-designer/subgraphs/) when a reusable region should become its own asset.

---

<a id="page-state-designer-getting-started-sample-scenes"></a>

# Sample Scenes

[View this page online](https://opsive.com/support/documentation/state-designer/getting-started/sample-scenes/)

Use the 15 sample scenes as a guided course through ordinary state flow, events, Subgraphs, persistence, and ECS. Reproduce each scene's result before copying its graph pattern.

## Open a sample

1. Open **Tools > Opsive > State Designer > Samples**.
2. Import or update the current sample content.
3. Confirm that every dependency on the selected card has a green check mark.
4. Select **Open Documentation** when available, then **Open Scene**.
5. Enter Play Mode and observe the state changes before editing the graph.

![The State Designer Samples Hub lists imported sample cards with preview images, dependency status, and enabled Open Scene buttons.](https://opsive.com/wp-content/uploads/2026/08/state-designer-getting-started-sample-hub.webp?v=ae3e7bbf7f98)

## Recommended learning order

| Order | Sample | Level | What to observe | Continue with |
| --- | --- | --- | --- | --- |
| 1 | Collision | Beginner | Physics callbacks make transition Conditions valid. | [Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/) |
| 2 | Events | Beginner | Local and global events cause state-machine responses. | [Events](https://opsive.com/support/documentation/state-designer/events/) |
| 3 | UI Menu | Beginner | Mutually exclusive panels are represented by explicit states. | [Menu Screen Flow](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/menu-screen-flow/) |
| 4 | Dialogue | Beginner | Button selections choose dialogue transitions. | [Dialogue Choice Flow](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/dialogue-choice-flow/) |
| 5 | Elevator | Beginner | Several doors or floors reuse one Subgraph with different overrides. | [Subgraphs](https://opsive.com/support/documentation/state-designer/subgraphs/) |
| 6 | Property Binding | Beginner | A Shared Variable stays synchronized with a C# property. | [Property Binding](https://opsive.com/support/documentation/state-designer/variables/property-binding/) |
| 7 | Subgraphs | Intermediate | Three doors reuse one Subgraph with different values. | [Subgraphs](https://opsive.com/support/documentation/state-designer/subgraphs/) |
| 8 | Save Load | Intermediate | Active state and supporting scene data are restored. | [Save/Load](https://opsive.com/support/documentation/state-designer/save-load/) |
| 9 | Animation Sync | Intermediate | NavMeshAgent velocity is converted into Animator data. | [Built-in Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/built-in-actions/) |
| 10 | Persistent Scenes A and B | Intermediate | One state machine remains active while scenes change. | [Persistent State Across Scenes](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/persistent-state-across-scenes/) |
| 11 | Player Controller | Advanced | Separate state machines own character movement and camera rotation. | [Built-in Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/built-in-actions/) |
| 12 | Subgraph Replacement | Advanced | A Subgraph Reference is reevaluated and replaced at runtime. | [Subgraphs](https://opsive.com/support/documentation/state-designer/subgraphs/) |
| 13 | Turn Based | Advanced | Two state machines alternate active control and can be ticked manually. | [Turn-Based Phase Loop](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/turn-based-phase-loop/) |
| 14 | Entities | Advanced | Baked and runtime-spawned entities run ECS states. | [Entity Baking](https://opsive.com/support/documentation/state-designer/entity-baking/) |

Persistent Scenes A and B form one lesson, so 15 cards produce 14 rows.

## Choose by goal

- **Learn ordinary transitions:** Collision, Events, UI Menu, and Dialogue.
- **Reuse graph content:** Elevator, Subgraphs, and Subgraph Replacement.
- **Share data:** Property Binding and Save Load.
- **Connect Unity systems:** Animation Sync and Player Controller.
- **Control lifetime or execution:** Persistent Scenes, Turn Based, and Entities.

## Verify before adapting

Select the active state machine in Play Mode and identify the current state, the transition that becomes valid, and the Action that changes the game. Copy the smallest graph pattern into project-owned content. Reimport a modified sample rather than treating its versioned sample folder as production content.

If the scene opens but the graph behaves unexpectedly, use [Debugging](https://opsive.com/support/documentation/state-designer/debugging/). If **Open Scene** is unavailable, confirm the current sample import and the package checks shown on the card.

---

<a id="page-state-designer-concepts"></a>

# Concepts

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/)

State Designer organizes gameplay into clear states, runs behavior through actions, controls changes with transition conditions, and shares values through a blackboard. Use these pages to understand each part and how they work together in a state machine.

## Understand state machines

- [What is a Finite State Machine?](https://opsive.com/support/documentation/state-designer/concepts/what-is-a-finite-state-machine/) introduces states, transitions, and structured gameplay flow.
- [Finite State Machines vs Behavior Trees](https://opsive.com/support/documentation/state-designer/concepts/finite-state-machines-vs-behavior-trees/) compares state control with decision-making.

## Build with State Designer

- [States](https://opsive.com/support/documentation/state-designer/concepts/states/) explains how states organize each behavior mode.
  - [Action State](https://opsive.com/support/documentation/state-designer/concepts/states/action-state/) runs actions in sequence or in parallel.
  - [Any](https://opsive.com/support/documentation/state-designer/concepts/states/any/) provides a shared path for transitions that can apply from multiple states.
  - [Subgraph Reference](https://opsive.com/support/documentation/state-designer/concepts/states/subgraph-reference/) inserts reusable state machine content into a parent graph.
- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/) explains how Actions perform behavior while a state is active.
  - [Built-in Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/built-in-actions/) helps locate the node category that owns a required operation.
- [Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/) explains the checks that allow transitions between states.
  - [Built-in Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/built-in-conditions/) helps locate the node category that owns a required decision.
- [Blackboard](https://opsive.com/support/documentation/state-designer/concepts/blackboard/) explains how states share values through variables.
- [Transition Evaluation and Priority](https://opsive.com/support/documentation/state-designer/concepts/transition-evaluation-and-priority/) explains evaluation timing, competing valid transitions, Any, and re-entry.
- [Common Graphs](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/) applies these concepts to recognizable gameplay and UI flows.

---

<a id="page-state-designer-concepts-what-is-a-finite-state-machine"></a>

# What is a Finite State Machine?

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/what-is-a-finite-state-machine/)

A finite state machine organizes behavior into clear modes and defines exactly when the system can move from one mode to another. After reading this page, you should be able to identify a state, transition, and condition, then follow the active path through a simple graph.

[Watch the finite state machine overview](https://www.youtube.com/watch?v=GArJC6B-OVs) for a visual introduction.

## Understand the parts

![Diagram showing states as nodes and transitions as directional connections between them.](https://opsive.com/wp-content/uploads/2026/03/StateDiagram-1024x328.png)

A finite state machine is built from a small set of parts:

- A **state** is the mode that is currently active, such as Patrol, Chase, or Attack.
- An **Action** performs the work associated with the active state.
- A **transition** connects one state to another.
- A **Condition** decides when its transition is allowed to run.

At any moment, the state machine has a well-defined active state. It remains there until a transition's conditions are satisfied, then exits the current state and enters the connected state.

## Follow one enemy scenario

![Enemy state machine connecting Patrol, Chase, and Attack states with transitions.](https://opsive.com/wp-content/uploads/2026/03/PatrolChaseAttack.png?v=1752bdfff6dd)

Consider an enemy with Patrol, Chase, and Attack states. It starts in Patrol. Detecting the player satisfies the condition that leads to Chase; reaching the player allows the transition to Attack. If the player escapes, another transition returns the enemy to Patrol.

Each state gives the enemy one clear mode, while the transitions show every permitted change. You can understand the possible flow without combining all of the movement, detection, and attack rules into one block of logic.

The same graph can grow without changing its basic model. For example, add a Flee state and connect it with a low-health condition:

![Enemy state machine extended with a Flee state for a low-health transition.](https://opsive.com/wp-content/uploads/2026/03/PatrolChaseAttackFlee.png?v=71d1f9435f31)

Flee is another mode, and the low-health check is another reason to transition. The existing Patrol, Chase, and Attack responsibilities remain distinct.

## How it runs

1. The state machine enters its starting state.
2. The active state's Actions perform their work.
3. The state machine evaluates the Conditions on transitions leaving that state.
4. When a transition is allowed, the current state exits and the connected state becomes active.
5. The same process repeats from the new state.

![State Designer Play Mode graph with one state highlighted as the active state.](https://opsive.com/wp-content/uploads/2026/03/PatrolChaseAttackFleeActive.png?v=16541327b199)

In Play Mode, State Designer highlights the active state and shows transitions as they occur. This lets you compare the graph's visible flow with the behavior you observe in the game.

## Choose a finite state machine when modes matter

Finite state machines are a good fit when behavior has stable modes, explicit changes, or clear phases. Common uses include animation control, gameplay modes, boss fight progression, and user-interface flow.

Start with a small graph whose states have clear responsibilities. Add a new state when the system needs a genuinely different mode, and add a transition when you can name the condition that permits that change.

## Related pages

- Learn how [States](https://opsive.com/support/documentation/state-designer/concepts/states/) organize each behavior mode.
- Learn how [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/) perform work in the active state.
- Learn how [Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/) control transitions.
- Build your first graph with [Getting Started](https://opsive.com/support/documentation/state-designer/getting-started/).
- **Cross-product comparison:** [Finite State Machines vs Behavior Trees](https://opsive.com/support/documentation/state-designer/concepts/finite-state-machines-vs-behavior-trees/) explains when State Designer or Behavior Designer is the clearer structure.

---

<a id="page-state-designer-concepts-finite-state-machines-vs-behavior-trees"></a>

# Finite State Machines vs Behavior Trees

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/finite-state-machines-vs-behavior-trees/)

Use the structure that makes the behavior easiest to understand and change. Finite state machines and behavior trees can solve many of the same problems, but they make different parts of the design visible.

A finite state machine emphasizes the mode that is active and the transitions that can change it. A behavior tree emphasizes the tasks that should be tried, their order, and what happens when a task succeeds, fails, or keeps running. Neither structure is automatically better or more advanced.

## Decide from the question you are asking

- Choose a finite state machine when the main question is, “Which mode is active, and what can move the system to another mode?”
- Choose a behavior tree when the main question is, “Which action should be tried now, and what should happen if it cannot run?”
- Use both only when separating broad modes from decisions makes the overall system clearer.

## Choose a finite state machine for explicit modes

![Finite state machine with distinct states connected by explicit transitions.](https://opsive.com/wp-content/uploads/2026/03/FSMOverview-1024x411.png)

Finite state machines work well when behavior has stable modes and each change should follow an explicit transition. They make entry, exit, and the currently active state easy to identify.

Typical scenarios include animation modes, gameplay phases, boss fight stages, and characters that move between clear states such as Patrol, Chase, and Attack. A state machine is also a good fit when the allowed transitions are part of the design and should be visible in the graph.

The tradeoff is that a graph with too many states and cross-connections can become difficult to follow. In that situation, divide the behavior into smaller responsibilities instead of adding every decision to one state machine.

## Choose a behavior tree for ordered decisions

![Behavior tree with branching tasks used for priority, sequence, and fallback decisions.](https://opsive.com/wp-content/uploads/2024/12/BehaviorTreesFSMsParallelism-1024x823.png)

Behavior trees work well when several actions may be valid and the system should evaluate them in a deliberate order. Selectors, Sequences, conditions, and fallback branches can express priorities and react to changing context.

Typical scenarios include choosing between AI actions, trying a preferred behavior before a fallback, and running a sequence of tasks that may succeed or fail. A behavior tree is useful when the order of evaluation is more important than naming one persistent mode.

The tradeoff is that deeply nested branches can make long-lived modes and their entry or exit rules harder to see. If the design is primarily about remaining in a mode until a specific transition occurs, a finite state machine may communicate it more directly.

## Behavior Designer terms in this comparison

The terms **Selector**, **Sequence**, **task**, and **Success**, **Failure**, or **Running** describe behavior-tree concepts used by Behavior Designer. They are included intentionally for comparison. State Designer organizes its graphs around **States**, **Transitions**, **Actions**, and **Conditions**; those terms describe different roles and should not be treated as interchangeable.

## Compare the design emphasis

| Decision point | State Designer finite state machine | Behavior Designer behavior tree |
| --- | --- | --- |
| What is most visible? | The active state and its possible transitions | The task path, evaluation order, and fallback behavior |
| What changes execution? | A transition condition or event | The result of a task and the behavior of its parent branch |
| What stays stable? | The current state until a transition is allowed | The traversal rules while tasks are evaluated or running |
| Common strength | Structured phases and explicit mode changes | Priority, sequence, and context-driven action selection |
| Common warning sign | Too many states or cross-connections | Too many nested branches or unclear long-lived modes |

## Use both when ownership stays clear

A state machine can manage broad modes such as Patrol, Combat, and Disabled while a behavior tree chooses actions within Combat. A behavior tree can also choose a goal while a state machine manages that goal's explicit phases. The useful boundary is the one that lets each graph answer one clear question without duplicating control over the same behavior.

## What State Designer emphasizes

![State Designer graph showing a small finite state machine with connected states.](https://opsive.com/wp-content/uploads/2026/03/SimpleFSMOverview.png?v=f02c0d3e6fe6)

State Designer focuses on state-driven control: distinct states, visible transitions, and runtime inspection of the active flow. This makes it a strong choice when the current mode and the rules for leaving it are central to the design, without implying that a behavior tree is unsuitable for other parts of the same system.

## Related concepts

- Start with [What is a Finite State Machine?](https://opsive.com/support/documentation/state-designer/concepts/what-is-a-finite-state-machine/) for the basic execution model.
- Learn how [States](https://opsive.com/support/documentation/state-designer/concepts/states/) organize a behavior mode.
- Learn how [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/) perform work while a state is active.
- Learn how [Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/) control transitions between states.

---

<a id="page-state-designer-concepts-blackboard"></a>

# Blackboard

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/blackboard/)

The blackboard is the list of Shared Variables available to a state machine. It lets states and actions use the same value, so one action can update information that another action reads without duplicating the data.

## In the editor

Create and organize variables in the Shared Variables pane. The example groups object and integer values for the Resource, Juice, and Club parts of the graph.

![The Shared Variables pane showing Resource, Juice, and Club variables in Graph scope.](https://opsive.com/wp-content/uploads/2026/02/Blackboard.png?v=d5e4c24ce892)

Select a compatible Shared Variable from a field in the Element Inspector. Here, the SetInteger action reads the Gather Animation Index variable for its Value.

![The SetInteger action using Gather Animation Index as its shared Value.](https://opsive.com/wp-content/uploads/2024/11/BlackboardAssignment.png?v=faede368cebb)

## How it runs

Every action field assigned to the same Shared Variable references the same value. In this example, the SetInt action stores 5 in Gather Animation Index. The SetInteger action shown above then reads that updated value.

![The SetInt action storing the value 5 in the Gather Animation Index shared variable.](https://opsive.com/wp-content/uploads/2024/11/BlackboardSetValue.png?v=55444e987db4)

## Choose a scope

Keep each variable in the narrowest scope that needs it:

- **Graph:** Available to the current graph and appropriate for most variables.
- **GameObject:** Available to state machines on the same GameObject.
- **Scene:** Available to state machines in the same scene.
- **Project:** Available to state machines throughout the project.

## Related pages

- [Variables](https://opsive.com/support/documentation/state-designer/variables/)
- [Variable Scope](https://opsive.com/support/documentation/state-designer/variables/scope/)
- [Accessing Variables](https://opsive.com/support/documentation/state-designer/variables/accessing-variables/)
- [States](https://opsive.com/support/documentation/state-designer/concepts/states/)
- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)

---

<a id="page-state-designer-concepts-states"></a>

# States

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/states/)

A State represents one mode of behavior, such as Idle, Patrol, Chase, or Attack. Use States to divide gameplay into clear modes so the graph shows what an object can do and how it moves between those modes.

![A State Designer graph connects Patrol, Chase, and Attack states with explicit transitions.](https://opsive.com/wp-content/uploads/2026/03/PatrolChaseAttack.png?v=1752bdfff6dd)

## In the editor

Create one State for each meaningful behavior mode and give it a name that describes that mode. Arrange the States so the main flow and the transitions between them are easy to follow.

For a GameObject workflow, add Actions to an [Action State](https://opsive.com/support/documentation/state-designer/concepts/states/action-state/) and configure them in the Element Inspector. Add Conditions to the outgoing transitions rather than to the State itself. The State organizes the mode, its Actions perform the work, and each transition's Conditions decide when the mode may change.

Most gameplay extensions do not require a new State type. Create a new Action when the mode needs different behavior, or a new Condition when a transition needs a different rule.

### Find and add a State

Press Space in the graph for the pointer-based selector, or open **Tools > Opsive > State Designer > State Palette** for a dockable browser. Search by State name or metadata, browse categories, and use **Favorites** for recurring entries. **Recent** keeps the last selected entries up to the limit in Preferences; `0` hides it. **Documentation** opens the entry's documentation when its capability supplies a URL.

The selector's **Filter** menu includes **Kind > Built-in / Codebase**, **Member > Methods / Get Properties / Set Properties**, **Scope > Static / Instance**, **Returns**, **Requires**, and **Execution > DOTS / Managed**. **Clear Filters** removes every constraint, and the number beside Filter is the active-filter count. A capability without the selected metadata is excluded. The dockable palette requires an open State Designer editor because it adds the selection to that window's active graph.

### Use State and group menus

Right-click one or more States or a group:

| Command | Result |
| --- | --- |
| **Cut / Copy / Duplicate / Delete** | Applies the standard graph operation to the complete selection and retains compatible internal transitions when copied. |
| **Enable / Disable** | Includes or excludes the selected State from execution. |
| **Collapse / Expand** | Hides or shows child content where supported. |
| **Set Color** | Adds an editor-only organizational color. |
| **Replace** | Changes the State type and preserves compatible serialized fields. Review the Inspector because unsupported fields cannot transfer. |
| **Edit Script / Locate Script** | Opens the State source or selects it in the Project window. |
| **Set as Start** | Connects the Start event to the selected State. |
| **Save as Subgraph** | Extracts a valid selected region using the workflow on [Subgraphs](https://opsive.com/support/documentation/state-designer/subgraphs/). |

The State hover toolbar exposes Enable/Disable, Collapse/Expand, adding a connected State, and **More**. **More** provides Replace, Set Color, Edit Script, and Locate Script.

### Use the State Inspector

Selecting a State displays its serialized fields plus a custom name and comment. The gear menu provides **Edit Script**, **Locate Script**, and **Reset**; Reset restores the State defaults and clears its custom name and comment. A field's watch icon displays its live value on the State without changing runtime behavior. Dragging a GameObject or Component onto a compatible State Inspector can create an Action State and assign the target automatically. Serialized editing commands are unavailable in Play Mode.

## How it runs

The Start event enters the first State. While that State is active, its Actions run according to its configuration. State Designer evaluates the outgoing transitions, and a valid transition moves execution into its destination State.

For example, Patrol can run movement Actions until a detection Condition allows the transition to Chase. Chase can move toward the target until an in-range Condition allows Attack. If the target is lost, another transition can return the state machine to Patrol.

During Play mode, the editor identifies the active State so you can follow the current mode and inspect why a transition does or does not occur.

## Key state choices

### Action State

Use an [Action State](https://opsive.com/support/documentation/state-designer/concepts/states/action-state/) for a GameObject workflow that runs one or more Actions. Its Execution Type controls whether those Actions run in Sequence or in Parallel.

### Any

Use [Any](https://opsive.com/support/documentation/state-designer/concepts/states/any/) for a transition that should be available from multiple normal States, such as interrupting Idle, Patrol, or Chase to enter Flee. Any is structural and does not run gameplay Actions.

### Subgraph Reference

Use a [Subgraph Reference](https://opsive.com/support/documentation/state-designer/concepts/states/subgraph-reference/) when a graph should load reusable State Designer behavior stored in a Subgraph asset. This keeps shared behavior in one place while allowing it to be used by other graphs.

## Related pages

- [What is a Finite State Machine?](https://opsive.com/support/documentation/state-designer/concepts/what-is-a-finite-state-machine/)
- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)
- [Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/)
- [Action State](https://opsive.com/support/documentation/state-designer/concepts/states/action-state/)
- [Any](https://opsive.com/support/documentation/state-designer/concepts/states/any/)
- [Subgraph Reference](https://opsive.com/support/documentation/state-designer/concepts/states/subgraph-reference/)

---

<a id="page-state-designer-concepts-states-action-state"></a>

# Action State

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/states/action-state/)

An Action State is the main state type for a GameObject workflow. Use it when a behavior mode needs one or more actions, such as moving, updating a value, or playing an animation.

## In the graph

The node displays its actions in their execution order, making the work performed by the state visible in the graph.

![An Action State node containing the BoolFlip, BoolToInt, and Play actions.](https://opsive.com/wp-content/uploads/2026/03/ActionState.png?v=87100b38356d)

## In the Inspector

Select the Action State to add, remove, enable, disable, and reorder its actions. The Execution Type setting determines whether those actions run one after another or at the same time.

![The Action State Inspector using Sequence execution with BoolFlip, BoolToInt, and Play enabled.](https://opsive.com/wp-content/uploads/2026/03/ActionStateExecutionType.png?v=c82497a53b0b)

GameObject Actions are stacked inside an Action State. Entity Actions use a separate ECS state-node workflow and are not added to this action list.

## How it runs

- **Sequence:** Actions run one at a time in list order. The state remains active while the current action runs and finishes after the final action finishes.
- **Parallel:** Actions start together. The state remains active while any enabled action is still running and finishes after all enabled actions finish.

Outgoing transitions still use Conditions to decide when the state machine can move to another state. A transition set to evaluate when the state finishes therefore waits for the last Sequence action or for all Parallel actions to finish.

## Choose an execution type

Use **Sequence** when one action must finish before the next begins. Use **Parallel** when the actions should run together and the state should wait for every enabled action to finish.

Most custom GameObject behavior should be added by creating a GameObject Action rather than a new state type. Use an Entity Action only when the behavior belongs in an ECS workflow.

## Related pages

- [States](https://opsive.com/support/documentation/state-designer/concepts/states/)
- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)
- [Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/)
- [GameObject Action](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-action/)
- [Entity Action](https://opsive.com/support/documentation/state-designer/new-nodes/entity-action/)
- [GameObject Condition](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-condition/)
- [Entity Condition](https://opsive.com/support/documentation/state-designer/new-nodes/entity-condition/)

---

<a id="page-state-designer-concepts-states-any"></a>

# Any

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/states/any/)

The Any state provides one shared transition source for conditions that should redirect the graph from several normal states. Use it for a global interrupt instead of duplicating the same outgoing transition on every state.

![The Any structural state node in a State Designer graph.](https://opsive.com/wp-content/uploads/2026/03/AnyNode.png?v=31e2359bd00f)

Any is structural: it does not run Actions and normal states do not transition into it. Its outgoing transitions point to the Action States that perform the actual behavior.

## Set it up in the graph

1. Add an **Any** state.
2. Add the destination Action State that should handle the interrupt.
3. Connect Any to that destination state.
4. Select the transition and add the Conditions that allow the interrupt.
5. Use **Continuous** evaluation when the condition should be checked while a normal state is active.

Keep a transition on its normal source state when only that state needs it. Use Any when the same rule genuinely applies across several states.

## Example: flee at low health

Suppose Idle, Patrol, and Chase should all stop when the character's health becomes low. Connect Any to a Flee Action State and place the low-health Condition on that one transition.

![The Any state connected to Flee so one low-health condition can interrupt normal states.](https://opsive.com/wp-content/uploads/2026/03/AnyToFlee.png?v=3a342998b1cf)

This replaces separate Idle-to-Flee, Patrol-to-Flee, and Chase-to-Flee transitions. Flee still owns the Actions that perform the escape behavior; Any only provides the shared route into it.

## How it runs

While Idle, Patrol, or Chase is active, State Designer can evaluate the Any-to-Flee transition. When the low-health Condition becomes valid, the current state exits and Flee becomes active. The Any state is never entered as the current behavior state.

Leave **Can Reenter** disabled for this persistent low-health check so the transition does not restart Flee while Flee is already active. Enable it only when a new interrupt should deliberately restart an already active destination state.

## Choose conditions and priority

![The Any-to-Flee transition Inspector showing the conditions that control the global interrupt.](https://opsive.com/wp-content/uploads/2026/03/AnyConditions.png?v=f85aaf9683e4)

- Use **All** Condition Mode when every Condition must be valid, or **Any** when one valid Condition is enough.
- Use **Continuous** evaluation for an immediate global interrupt. Other evaluation modes are better suited to transitions that should wait for state or Action progress.
- Reorder Any's outgoing transitions to set their priority. When more than one transition is valid, the first valid transition in the list runs for that update, so place the most important interrupt first.
- Enable only the transitions that should currently participate in the graph.

## Related pages

- [States](https://opsive.com/support/documentation/state-designer/concepts/states/) explains how normal states organize behavior.
- [Action State](https://opsive.com/support/documentation/state-designer/concepts/states/action-state/) explains where GameObject Actions run.
- [Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/) explains Condition Mode and Evaluation Mode.
- [GameObject Condition](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-condition/) shows how to create a custom transition check.

---

<a id="page-state-designer-concepts-states-subgraph-reference"></a>

# Subgraph Reference

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/states/subgraph-reference/)

A Subgraph Reference places reusable state machine behavior inside another graph. Use it when the same group of states, Actions, and transitions is needed in several graphs, or when a parent graph should remain focused on its high-level flow.

## In the editor

Add a Subgraph Reference state to the parent graph and assign one or more Subgraph assets to it.

![A Subgraph Reference state placed in a State Designer graph.](https://opsive.com/wp-content/uploads/2026/03/SubgraphReferenceState.png?v=5b0ead8e7cd2)

Add outgoing transitions to the Subgraph Reference when the parent graph needs to define what happens after the referenced behavior finishes. If several Subgraphs are assigned to one reference, their order in the list controls the order in which they are processed.

Use Shared Variable Overrides when the parent graph should provide different values without changing the reusable Subgraph asset.

![The Subgraph Reference inspector mapping a source Shared Variable to an override value.](https://opsive.com/wp-content/uploads/2026/03/SubgraphReferenceOverride.png?v=57c99a014611)

Each override maps a **Source** variable from the Subgraph to the **Override** value or variable supplied by the parent graph. Leave an override empty when the Subgraph should keep its own default value.

## How it runs

Subgraph Reference is a structural entry point. When execution reaches it, State Designer injects the referenced Subgraph content, and the States and Actions inside that content perform the gameplay behavior. Conditions on its transitions continue to control movement between States.

If a State inside the Subgraph reaches its end without an outgoing transition, execution can continue through an outgoing transition on the Subgraph Reference in the parent graph. This gives the parent one clear place to decide what follows the reusable behavior.

When one reference contains multiple Subgraphs, State Designer processes them in list order.

## Key reuse choices

Use one Subgraph with different overrides when the structure should remain the same but values such as a target, speed, timer, or flag should vary by parent graph.

For an advanced setup, the selected Subgraph can change at runtime. After changing that selection, call `StateMachine.ReevaluateSubgraphReferences()`. State Designer then reevaluates the references and rebuilds the injected content using the current selection and override mappings.

## Related pages

- [States](https://opsive.com/support/documentation/state-designer/concepts/states/)
- [Action State](https://opsive.com/support/documentation/state-designer/concepts/states/action-state/)
- [Subgraphs](https://opsive.com/support/documentation/state-designer/subgraphs/)
- [Variable Scope](https://opsive.com/support/documentation/state-designer/variables/scope/)
- [Accessing Variables](https://opsive.com/support/documentation/state-designer/variables/accessing-variables/)

---

<a id="page-state-designer-concepts-actions"></a>

# Actions

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/actions/)

An Action performs behavior while a state is active. Use Actions for work such as moving toward a target, playing an animation, changing a value, triggering an effect, or calling another gameplay system.

Most project-specific State Designer behavior belongs in an Action. States organize that behavior into modes, while Conditions decide when transitions may move the state machine to another mode.

## In the editor

For a GameObject workflow, select an [Action State](https://opsive.com/support/documentation/state-designer/concepts/states/action-state/), add the Actions that should run in that state, and configure each Action in the Element Inspector. The same Action type can be reused in multiple states with different values.

An Action State can run its Actions as a **Sequence** or in **Parallel**. Choose Sequence when one Action should finish before the next starts. Choose Parallel when the Actions should run together.

Entity Actions use the ECS workflow and appear as their own state logic rather than as GameObject Actions inside an Action State. Choose that workflow when the project already uses ECS or profiling shows that the behavior must scale across many entities.

### Use Action list controls

An Action State's list supports Enable/Disable, drag reordering, **+** to open the searchable Action selector, and **-** to remove the selected row. Search, Favorites, Recent, Documentation, and the **Kind**, **Member**, **Scope**, **Returns**, **Requires**, and **Execution** filters work as described on the [States](https://opsive.com/support/documentation/state-designer/concepts/states/) page, but the results are limited to compatible Actions.

Right-click an Action row for **Replace**, **Rename**, **Edit Script**, **Locate Script**, **Copy**, **Paste**, **Duplicate**, or **Delete**. Copy, Duplicate, and Delete can use a multi-row selection; Replace and Rename require one row. Right-click blank list space to paste copied Actions. Dragging a GameObject or Component onto a supported Action State area opens a filtered Action selector and assigns the target automatically.

The Element Inspector gear provides **Edit Script**, **Locate Script**, and **Reset** for the selected Action. A watch icon shows a supported field's live value on the State without affecting execution. Serialized list edits are unavailable in Play Mode.

## How it runs

When a state becomes active, its Actions perform the work for that mode. In a Sequence, the state advances through its Actions in order and finishes after the final Action completes. In Parallel, the Actions start together and the state finishes after all active Actions complete.

Actions do not decide transitions. Conditions on outgoing transitions determine whether the state machine can leave the current state. Keeping behavior in Actions and decisions in Conditions makes the graph easier to read and debug.

## Key choices and example

Create an Action when something should happen in the game. Create a Condition when the state machine only needs to answer a yes-or-no question before taking a transition.

Keep each Action focused on one job. Smaller Actions are easier to reuse, configure, and combine than one Action that controls an entire behavior.

For example, a Chase state can combine one Action that moves toward a target with another that turns to face it. Conditions on its outgoing transitions can check whether the target is close enough to enter Attack or has been lost so the state machine should return to Patrol.

For most custom behavior, start with a GameObject Action. Use an Entity Action for data-oriented behavior that needs ECS execution, and optimize only where the project benefits from it.

Use [Built-in Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/built-in-actions/) to choose a category before searching the Action selector. The selector remains the source of truth for capabilities supplied by currently installed integrations and project code.

## Related pages

- [States](https://opsive.com/support/documentation/state-designer/concepts/states/)
- [Action State](https://opsive.com/support/documentation/state-designer/concepts/states/action-state/)
- [Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/)
- [GameObject Action](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-action/)
- [Entity Action](https://opsive.com/support/documentation/state-designer/new-nodes/entity-action/)
- [Built-in Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/built-in-actions/)

---

<a id="page-state-designer-concepts-actions-built-in-actions"></a>

# Built-in Actions

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/actions/built-in-actions/)

Use this index to choose the Action category that owns a gameplay operation before opening the searchable selector. The selector also includes compatible methods, properties, integrations, and project code, so its results can be broader than the built-in package catalog.

## Find an Action

Select an Action State, use **+**, and search by a verb or affected Unity feature. Use **Favorites** for common choices and **Recent** for the current task. Clear filters when a known Action is hidden.

The **Kind**, **Member**, **Scope**, **Returns**, **Requires**, and **Execution** filters distinguish built-ins from codebase members and restrict the workflow or installed dependency. Use **Documentation** on an entry when a focused page is available.

## Start with common categories

| Goal | Category | Typical use |
| --- | --- | --- |
| Print or inspect a value | **Debug** | Log a message while learning or isolating a graph. |
| Wait or measure time | **Time** | Delay a sequence, store a timestamp, or control a timed phase. |
| Change a Shared Variable | **Variables**, **Math**, or **Conversions** | Set, calculate, compare, or convert reusable data. |
| Enable, disable, spawn, or destroy an object | **GameObject** or **Resources** | Control scene-object lifetime and visibility. |
| Move or rotate an object | **Transform**, **Rigidbody**, or **Character Controller** | Apply the movement system that already owns the object. |
| Navigate an agent | **NavMesh** | Set a destination, stop navigation, or inspect agent state. |
| Play visual or audio feedback | **Animator**, **Animation**, **Audio**, **Particles**, or **Rendering** | Drive presentation from a State. |
| Read player input | **Input > Input System** or **Input > Input Manager** | Use the input backend configured by the project. |
| Open, close, or update UI | **UI** or **TextMeshPro** | Change panels, controls, and labels. |
| Send graph communication | **Events** or **State Designer** | Send events or control another state machine. |
| Load or preserve state | **Save Load** or **Scene Management** | Save data or change scenes with explicit ownership. |

Additional built-in categories include **Camera**, **IList**, **Physics**, **Physics 2D**, and **Utility**. Choose the system that already owns the object rather than applying Transform, Rigidbody, Character Controller, and NavMesh movement to the same object at once.

## Choose GameObject or Entity execution

Start with GameObject Actions when the behavior uses Components and scene objects. Use Entity Actions only when the data belongs in ECS and the authoring/baking path is configured. The Entities dependency does not require every State to use Entity Actions.

## Verify an unfamiliar Action

Create a temporary Action State containing only that Action, fixed input values, and one visible or logged result. Enter Play Mode, observe completion status, and confirm the affected object. Add it to the production State only after its result and ownership are clear.

## Related pages

- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)
- [Action State](https://opsive.com/support/documentation/state-designer/concepts/states/action-state/)
- [GameObject Action](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-action/)
- [Entity Action](https://opsive.com/support/documentation/state-designer/new-nodes/entity-action/)
- [Debugging](https://opsive.com/support/documentation/state-designer/debugging/)

---

<a id="page-state-designer-concepts-conditions"></a>

# Conditions

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/conditions/)

A Condition answers a yes-or-no question for a transition. Use Conditions for checks such as whether a timer has elapsed, a target is in range, a variable has a particular value, or the player pressed an input.

States organize behavior into modes, Actions perform the work for the active state, and Conditions decide whether the state machine may follow a transition to another state.

## In the editor

Select a transition and add its Conditions in the Element Inspector. Conditions belong to the transition rather than to either connected state.

The transition also owns two settings that control how its Conditions are used:

- **Condition Mode** combines multiple Conditions. **All** requires every Condition to be valid, while **Any** allows the transition when at least one is valid.
- **Evaluation Mode** decides when State Designer checks the Conditions.

Use a GameObject Condition for most checks that work with scene objects and Unity components. Use an Entity Condition when the project needs the check to run through an ECS workflow.

### Use transition and Condition menus

Right-click a transition to use these commands:

- **Copy Transition** and **Paste Transition** copy compatible Condition and runtime settings without changing either endpoint.
- **Set Color** and **Reset Color** change its editor-only color.
- **Route > Bezier / Straight / Orthogonal** changes the drawing style.
- **Outgoing Anchor** and **Incoming Anchor** use **Auto**, **Top**, **Bottom**, **Left**, or **Right**.
- **Add Waypoint**, **Remove Waypoint**, and **Clear Waypoints** control manual bends.
- **Reset Layout** restores routing, anchors, color, and waypoints.
- **Delete** removes the transition.

Hover over a transition to inspect its Condition Mode, Evaluation Mode, and Condition summary without changing the selection. Disabled Condition rows are marked as off.

The Conditions list supports Enable/Disable, drag reordering, **+** to open the searchable Condition selector, and **-** to remove the selected row. Search, Favorites, Recent, Documentation, and the **Kind**, **Member**, **Scope**, **Returns**, **Requires**, and **Execution** filters work as described on the [States](https://opsive.com/support/documentation/state-designer/concepts/states/) page, but results are limited to compatible Conditions.

Right-click a Condition row for **Replace**, **Rename**, **Edit Script**, **Locate Script**, **Copy**, **Paste**, **Duplicate**, or **Delete**. Copy, Duplicate, and Delete can use a multi-row selection; Replace and Rename require one row. Right-click blank list space to paste copied Conditions. Dragging a GameObject or Component onto a transition opens a compatible Condition selector and assigns the target automatically. Serialized list edits are unavailable in Play Mode.

## How it runs

Each Condition reports whether its rule is currently valid. The transition combines those results according to Condition Mode, then changes state only when the selected Evaluation Mode allows the check.

- **Continuous** checks while the source state is active and is the default behavior.
- **On State Finished** checks when the state reports that it has finished.
- **On Iteration Complete** checks after the state's Actions complete one iteration.

Conditions should remain focused on decisions. If something needs to move, animate, change a value, or otherwise affect the game world, that work belongs in an Action.

## Important choices and example

Use **All** when every requirement must pass, such as a target being both visible and within attack range. Use **Any** when several different checks may allow the same transition, such as hearing a sound or seeing the target.

For a Patrol-to-Chase transition, a detection Condition decides whether a target has been found. With Continuous evaluation, the state machine can enter Chase as soon as the target is detected. With On Iteration Complete, Patrol can finish its current pass before switching.

Keeping behavior in Actions and decision-making in Conditions makes each state and transition easier to understand and debug.

Use [Built-in Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/built-in-conditions/) to choose a category before searching the Condition selector. Use [Transition Evaluation and Priority](https://opsive.com/support/documentation/state-designer/concepts/transition-evaluation-and-priority/) when several transitions can be valid at once or a graph loops unexpectedly.

## Related pages

- [States](https://opsive.com/support/documentation/state-designer/concepts/states/)
- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)
- [Action State](https://opsive.com/support/documentation/state-designer/concepts/states/action-state/)
- [GameObject Condition](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-condition/)
- [Entity Condition](https://opsive.com/support/documentation/state-designer/new-nodes/entity-condition/)
- [Built-in Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/built-in-conditions/)
- [Transition Evaluation and Priority](https://opsive.com/support/documentation/state-designer/concepts/transition-evaluation-and-priority/)

---

<a id="page-state-designer-concepts-conditions-built-in-conditions"></a>

# Built-in Conditions

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/conditions/built-in-conditions/)

Use this index to choose the Condition category that owns a yes-or-no decision before opening the searchable selector. Conditions should inspect state; work that changes the game belongs in an Action.

## Find a Condition

Select a transition, use **+** in its Conditions list, and search by the question being asked. Search, Favorites, Recent, Documentation, and the **Kind**, **Member**, **Scope**, **Returns**, **Requires**, and **Execution** filters behave like the Action selector while showing only compatible Conditions.

## Start with common categories

| Question | Category | Typical use |
| --- | --- | --- |
| Has enough time passed? | **Time** | Timers, elapsed duration, and phase boundaries. |
| Did input occur? | **Input > Input System** or **Input > Input Manager** | Button, key, axis, and pointer decisions. |
| Does a value match? | **Variables**, **Math**, or **Utility** | Equality, ranges, Boolean state, and other data decisions. |
| Did physics interaction occur? | **Physics** or **Physics 2D** | Collision, trigger, cast, overlap, or Rigidbody state. |
| Is an object active or available? | **GameObject**, **IList**, or **Resources** | Object state, collection contents, and asset availability. |
| Did animation reach a state? | **Animator** or **Animation** | Animator parameters, state, or clip progress. |
| Has navigation reached its goal? | **NavMesh** | Path, destination, and stopping decisions. |
| Did an event arrive? | **Events** or **State Designer** | Local/global event and state-machine status decisions. |
| Is UI or text in the expected state? | **UI** or **TextMeshPro** | Selection, toggle, field, or label decisions. |
| Is saved or scene state ready? | **Save Load** or **Scene Management** | Persistence and scene-lifecycle gates. |

Additional built-in categories include **Camera** and **Character Controller**. Use the narrowest Condition that reads the authoritative system instead of reproducing the same decision with loosely synchronized variables.

## Verify an unfamiliar Condition

Connect one source State to a visible destination, add only the Condition under test, and use a fixed input or controlled scene setup. Watch the transition hover summary and active-state change. Add other Conditions only after the single rule behaves correctly.

## Related pages

- [Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/)
- [Transition Evaluation and Priority](https://opsive.com/support/documentation/state-designer/concepts/transition-evaluation-and-priority/)
- [GameObject Condition](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-condition/)
- [Entity Condition](https://opsive.com/support/documentation/state-designer/new-nodes/entity-condition/)
- [Debugging](https://opsive.com/support/documentation/state-designer/debugging/)

---

<a id="page-state-designer-concepts-transition-evaluation-and-priority"></a>

# Transition Evaluation and Priority

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/transition-evaluation-and-priority/)

Use transition settings to control when Conditions are checked and which destination wins when several transitions are valid. Most unexpected loops and skipped states come from evaluation timing or transition order rather than the State itself.

## In the editor

Select a transition to configure its Conditions, **Condition Mode**, and **Evaluation Mode** in the Element Inspector.

![The State Designer transition Inspector configures a Timer Condition and its duration.](https://opsive.com/wp-content/uploads/2026/02/TimerElementInspector.png?v=718045b49548)

- **Condition Mode: All** requires every enabled Condition to be valid.
- **Condition Mode: Any** allows one valid Condition to permit the transition.
- **Continuous** evaluates while the source State is active.
- **On State Finished** evaluates when the State finishes.
- **On Iteration Complete** evaluates after an Action State completes one Action iteration.

Disabled Condition rows do not contribute. An empty or incorrectly filtered Condition list may therefore make the transition behave differently from its visible label or intended design.

## Resolve competing transitions

When several outgoing transitions are eligible in the same evaluation pass, their serialized order determines which is considered first. Put the most specific or urgent route before a broad fallback.

For a Chase state:

1. Put **Health Low → Flee** before ordinary combat choices when survival must win.
2. Put **Target In Range → Attack** before **Target Lost → Patrol** when the target checks could overlap for one frame.
3. Keep a broad timeout or default route last.

Do not encode priority only through graph position. Moving a line for readability does not necessarily change serialized transition order. Inspect and reorder the owning transition list where the editor exposes it, then verify the result in Play Mode.

## Choose evaluation timing

Use **Continuous** for perception, input, health, or another rule that should interrupt an active state. Use **On State Finished** when the current work must complete before leaving. Use **On Iteration Complete** when a repeating Action sequence should finish one pass before the decision is reconsidered.

Continuous evaluation is responsive but can expose short-lived values and cause rapid state changes. A finishing evaluation is predictable but may delay urgent reactions. Choose according to gameplay ownership, not as a performance shortcut.

## Use Any for shared interrupts

The Any State represents one transition source that can apply while several ordinary States are active.

![The Any state routes a low-health interrupt from normal behavior into Flee.](https://opsive.com/wp-content/uploads/2026/03/AnyToFlee.png?v=3a342998b1cf)

Use Any for a truly shared interrupt such as death, stun, or low-health flee. Do not use it as a replacement for every duplicated transition: the destination and Conditions must be valid from all States where the interrupt may occur.

## Control re-entry and loops

Allow re-entry only when entering the same State again should restart its Actions and lifecycle. Otherwise, a transition back to the active State can repeatedly reinitialize work, reset timers, or emit events.

When a graph loops unexpectedly:

1. Pause Play Mode on the first repeated State.
2. Inspect its outgoing transitions and the live Condition values.
3. Check for a continuously true Condition, an Any transition, or a self-transition with re-entry.
4. Add a state change, cooldown, consumed event, or finishing boundary so the Condition becomes false after use.

## Verify in Play Mode

Build a State with two outgoing transitions. Make both Conditions valid deliberately, record which destination wins, then reverse their order and test again. Restore the intended priority and make one Condition false. This controlled test proves the order and evaluation mode before the rules depend on live gameplay data.

## Troubleshooting

| Symptom | Check | Fix |
| --- | --- | --- |
| A lower-priority destination wins. | Serialized transition order and overlapping valid Conditions. | Move the specific/urgent transition before the fallback and retest. |
| A transition never runs. | Evaluation Mode and whether the source State ever finishes or completes an iteration. | Use the timing that matches the State lifecycle. |
| A State exits immediately. | Continuously true Conditions and default values. | Initialize the value before entry or choose a finishing evaluation. |
| The graph flickers between two States. | Opposing Conditions, re-entry, and values changed on entry/exit. | Add hysteresis, a cooldown, or one stable intermediate State. |
| Any interrupts an inappropriate State. | The interrupt is globally eligible while that State is active. | Narrow the Condition or use explicit transitions only from eligible States. |

## Related pages

- [Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/)
- [States](https://opsive.com/support/documentation/state-designer/concepts/states/)
- [Any](https://opsive.com/support/documentation/state-designer/concepts/states/any/)
- [Timed State Cycle](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/timed-state-cycle/)
- [Flee at Low Health](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/flee-at-low-health/)
- [Debugging](https://opsive.com/support/documentation/state-designer/debugging/)

---

<a id="page-state-designer-concepts-common-graphs"></a>

# Common Graphs

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/)

## Solve a gameplay flow

Common Graphs show how States, Actions, Conditions, transitions, Shared Variables, and Subgraphs fit together to solve recognizable problems. Each page describes the graph shape, the transition settings that matter, and a Play Mode result you can verify.

These are adaptable patterns rather than downloadable graphs. Keep the state and transition structure, then substitute the movement, combat, animation, audio, or project-specific Actions that fit your game.

## Illustrated walkthroughs

**[Patrol, Chase, and Attack](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/patrol-chase-and-attack/)** - Moves an agent through perception, pursuit, and attack-range states.

**[Flee at Low Health](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/flee-at-low-health/)** - Uses Any for one high-priority interrupt from several ordinary states.

**[Timed State Cycle](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/timed-state-cycle/)** - Combines Timer, input, and State Finished transitions in a repeating flow.

**[React to an Event](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/react-to-an-event/)** - Starts a response when another graph or script sends a named event.

**[Reusable Attack Subgraph](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/select-a-reusable-attack-subgraph/)** - Swaps melee and ranged behavior behind one parent-graph state.

These screenshot-backed guides remain visible beneath **Common Graphs** in the documentation menu.

## More patterns

The remaining patterns are summarized together here so the menu stays focused. Open one when its graph shape matches the problem you are solving.

**[Attack with Cooldown](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/attack-with-cooldown/)** - Shares one ready timestamp between the attack Action and its transition Condition.

**[Toggle an Interaction](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/toggle-an-interaction/)** - Models a door or switch with stable and in-progress states.

**[Menu Screen Flow](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/menu-screen-flow/)** - Keeps mutually exclusive UI screens in explicit states and uses button Conditions to navigate.

**[Dialogue Choice Flow](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/dialogue-choice-flow/)** - Maps each visible response to an explicit transition and returns the selected branch to the conversation owner.

**[Turn-Based Phase Loop](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/turn-based-phase-loop/)** - Alternates player and opponent phases without allowing both controllers to act at once.

**[Save and Resume a State Machine](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/save-and-resume-a-state-machine/)** - Chooses the data boundary and verifies an active-state round trip.

**[Persistent State Across Scenes](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/persistent-state-across-scenes/)** - Keeps one owner alive while scene-local references are rebound.

**[Animation-Driven Locomotion](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/animation-driven-locomotion/)** - Separates locomotion modes from Animator and movement Actions.

## Adapt a pattern

Name states after durable modes such as Patrol or Open, and put yes-or-no decisions on transitions. Put work that changes the game in Actions. Use [Shared Variables](https://opsive.com/support/documentation/state-designer/concepts/blackboard/) when both sides of a transition need the same target, health value, cooldown timestamp, or selection index.

Start with the smallest useful graph, verify each transition in Play Mode, and add an [Any](https://opsive.com/support/documentation/state-designer/concepts/states/any/) interrupt or a [Subgraph Reference](https://opsive.com/support/documentation/state-designer/concepts/states/subgraph-reference/) only when the shared route or reusable behavior makes the graph easier to follow.

---

<a id="page-state-designer-concepts-common-graphs-patrol-chase-and-attack"></a>

# Patrol, Chase, and Attack

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/patrol-chase-and-attack/)

Use this graph when an agent should patrol until it detects a target, pursue that target, and attack only at close range.

## In the editor

1. Create a GameObject Shared Variable named Target, then assign the target at runtime or from the Inspector.
2. Connect Start to Patrol, and add Patrol, Chase, and Attack Action States from left to right.
3. Connect Patrol to Chase. Add **Is In Line Of Sight**, select Target as the other GameObject, and use **Continuous** evaluation.
4. Connect Chase to Attack. Add **Within Distance**, select Target, and set the attack distance.
5. Connect Chase back to Patrol. Add another **Is In Line Of Sight** Condition configured to require blocked line of sight.
6. Connect Attack back to Chase with **State Finished** so the pursuit decision is evaluated again after the attack Action completes.

![Patrol, Chase, and Attack states connected by explicit perception and range transitions.](https://opsive.com/wp-content/uploads/2026/03/PatrolChaseAttack.png?v=1752bdfff6dd)

The Patrol and Chase states should contain Actions that remain Running while they perform their mode. Attack can contain a finite animation, damage, or project-specific combat sequence.

## How it runs

Patrol remains active until the target is visible. Chase then runs while the target stays visible and outside attack range. Entering range activates Attack; when the attack finishes, the graph returns to Chase and reevaluates range and visibility.

If the target moves out of sight during Chase, the blocked-line-of-sight transition returns the agent to Patrol. If the game should search the last known position first, insert a Search state between Chase and Patrol and store that position in a Shared Variable.

## Key choices

- Set the Chase-to-Attack and Chase-to-Patrol transitions to **Continuous** so movement can change the active mode immediately.
- Use **All** Condition Mode when Attack also requires a valid target, ammunition, or another rule.
- Keep sensing in Conditions and movement or combat in Actions. This makes each transition explain why the mode changed.
- Add the [Attack with Cooldown](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/attack-with-cooldown/) pattern when returning from Attack should not permit an immediate second attack.

## Verify in Play Mode

Move the target through the detection and attack boundaries. Confirm that the active highlight advances Patrol to Chase to Attack, returns to Chase after the attack finishes, and returns to Patrol when sight is lost.

## Related pages

- [States](https://opsive.com/support/documentation/state-designer/concepts/states/)
- [Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/)
- [Shared Variables](https://opsive.com/support/documentation/state-designer/concepts/blackboard/)
- [Attack with Cooldown](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/attack-with-cooldown/)

---

<a id="page-state-designer-concepts-common-graphs-flee-at-low-health"></a>

# Flee at Low Health

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/flee-at-low-health/)

Use this graph when low health should interrupt several ordinary states through one shared, high-priority route.

## In the editor

1. Create a float Shared Variable named Health.
2. Add an **Any** state above the ordinary Idle, Patrol, Chase, and Attack flow.
3. Add a Flee Action State and connect Any to Flee.
4. On the Any-to-Flee transition, add **Float Comparison**, compare Health with the entry threshold, and use **Less Than Or Equal To**. A value such as `25` is a useful starting example.
5. Set the transition to **Continuous** evaluation and leave **Can Reenter** disabled.
6. Connect Flee to a deliberate recovery state, such as Patrol. Add another **Float Comparison** that requires Health to be greater than or equal to a higher recovery threshold, such as `40`.

![The Any state routes low health from the normal behavior flow into Flee.](https://opsive.com/wp-content/uploads/2026/03/AnyToFlee.png?v=3a342998b1cf)

Flee should contain a movement or defensive Action that remains Running until the recovery transition becomes valid.

## How it runs

State Designer evaluates the Any-to-Flee transition while any ordinary state is active. When Health reaches the entry threshold, the current state ends and Flee starts. Any itself never becomes the active behavior state.

The higher recovery threshold prevents the graph from rapidly switching near one value. At Health 30, for example, the agent remains in Flee because it has not recovered to 40. Once the recovery transition succeeds, Patrol becomes active.

## Key choices

- Put the most important Any transition first when the graph has several global interrupts.
- Leave **Can Reenter** disabled for a persistent low-health condition so Flee is not restarted every evaluation.
- Use different entry and recovery thresholds. A single shared boundary can cause visible state chatter when health regeneration and damage alternate near that value.
- Choose the return state explicitly. Any does not remember and restore the state that it interrupted.

## Verify in Play Mode

Change Health while Patrol, Chase, and Attack are active. Each state should enter the same Flee state at or below the entry threshold. Confirm that Flee does not restart while already active and does not exit until Health reaches the recovery threshold.

## Related pages

- [Any](https://opsive.com/support/documentation/state-designer/concepts/states/any/)
- [Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/)
- [Shared Variables](https://opsive.com/support/documentation/state-designer/concepts/blackboard/)
- [Patrol, Chase, and Attack](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/patrol-chase-and-attack/)

---

<a id="page-state-designer-concepts-common-graphs-attack-with-cooldown"></a>

# Attack with Cooldown

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/attack-with-cooldown/)

Use this graph when an attack request should enter the Attack state only after a shared cooldown is ready.

## In the editor

1. Create a float Shared Variable named Next Attack Time.
2. Add Ready and Attack Action States. Put **Idle** in Ready so the state remains Running while it waits for a request.
3. Connect Ready to Attack. Add the input, target, or range Condition that requests the attack, then add **Cooldown Ready** and assign Next Attack Time.
4. Set the Ready-to-Attack transition's Condition Mode to **All** and Evaluation Mode to **Continuous**.
5. In Attack, add the project-specific attack Actions and **Start Cooldown**. Assign Next Attack Time to the Action and set the desired Duration.
6. Connect Attack back to Ready with **State Finished**.

Both **Start Cooldown** and **Cooldown Ready** must reference the same Shared Variable and make the same scaled-versus-unscaled-time choice.

## How it runs

Ready accepts an attack request only when the current time has reached Next Attack Time. Attack performs its Actions, stores a new ready timestamp through Start Cooldown, and returns to Ready when the state finishes. Further requests cannot take the Ready-to-Attack transition until Cooldown Ready becomes valid.

Put Start Cooldown before the attack Actions when the delay should begin as soon as Attack starts. Put it after those Actions when the full delay should begin after the animation or ability completes.

## Key choices

- Keep **Reset On State Machine Start** enabled when a newly started graph should attack immediately. Disable it when the timestamp must survive a pause, restore, or another owner of the same variable.
- **Wait** on Start Cooldown delays the Action when a cooldown is already active, **Restart** starts a fresh duration, and **Finish Without Restart** preserves the active timestamp.
- Use unscaled time for UI or pause-independent abilities; otherwise keep both nodes on scaled time.
- Store separate ready-time variables for abilities that have independent cooldowns.

## Verify in Play Mode

Request the attack repeatedly. Confirm that Attack becomes active once, returns to Ready, and cannot reactivate until the configured duration has elapsed. Inspect Next Attack Time to confirm that Start Cooldown updates the same value read by Cooldown Ready.

## Related pages

- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)
- [Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/)
- [Shared Variables](https://opsive.com/support/documentation/state-designer/concepts/blackboard/)
- [Patrol, Chase, and Attack](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/patrol-chase-and-attack/)

---

<a id="page-state-designer-concepts-common-graphs-timed-state-cycle"></a>

# Timed State Cycle

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/timed-state-cycle/)

Use this graph for a repeating sequence in which one transition waits for time, another responds to input or gameplay, and a finite state returns to the beginning.

## In the editor

1. Connect Start to Idle, then add Patrol and Log states and connect Idle to Patrol, Patrol to Log, and Log back to Idle.
2. Select the Idle-to-Patrol transition, replace its default Condition with **Timer**, and set the Duration.
3. Put the patrol movement Action in Patrol. Add the input or gameplay Condition that should allow Patrol-to-Log.
4. Put a finite **Log** or other one-shot Action in the final state.
5. Keep **State Finished** on the Log-to-Idle transition.

![Idle, Patrol, and Log form a repeating State Designer cycle.](https://opsive.com/wp-content/uploads/2026/03/IdlePatrolLog.png?v=bc2449f52ae1)

![The Idle-to-Patrol transition uses a Timer Condition with a configured duration.](https://opsive.com/wp-content/uploads/2026/02/TimerElementInspector.png?v=718045b49548)

## How it runs

Start activates Idle. Timer starts when Idle runs and allows the first transition after its duration. Patrol then stays active until its own Condition becomes valid. Log performs its finite Action, reports Finished, and immediately returns to Idle through State Finished. Entering Idle starts the transition timer for the next cycle.

## Key choices

- Use a **Timer** Condition when the source state's behavior should continue while time passes.
- Use a **Wait** Action when waiting is itself part of an Action State's Sequence or Parallel work.
- Use **On Iteration Complete** when a repeating state should finish its current Action iteration before checking the transition.
- Keep **Continuous** for input or gameplay changes that should interrupt the source state immediately.

## Verify in Play Mode

Watch the active highlight remain on Idle for the configured duration, move to Patrol, and enter Log only when its Condition succeeds. After Log finishes, the graph should return to Idle and begin a fresh timed cycle.

## Related pages

- [Overview](https://opsive.com/support/documentation/state-designer/overview/)
- [Action State](https://opsive.com/support/documentation/state-designer/concepts/states/action-state/)
- [Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/)
- [Toggle an Interaction](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/toggle-an-interaction/)

---

<a id="page-state-designer-concepts-common-graphs-react-to-an-event"></a>

# React to an Event

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/react-to-an-event/)

Use this graph when another state machine or script should start a response without the receiving graph polling the sender every update.

## In the editor

1. Add Waiting and React Action States. Put **Idle** in Waiting so it remains Running.
2. Connect Waiting to React and add **Has Received Event** to the transition.
3. Enter a nonempty Event Name, such as `TargetSpotted`, and use **Continuous** evaluation.
4. Choose targeted or global delivery. For targeted delivery, assign the receiving state machine's GameObject.
5. Optionally assign Stored Value Shared Variables when React needs an event argument such as the detected target.
6. Put the response Actions in React, then connect React back to Waiting with **State Finished**.
7. Add **Send Event** to the sending graph and configure the same Event Name, delivery choice, target, and argument types.

![The Send Event Action targets a named event and can include optional arguments.](https://opsive.com/wp-content/uploads/2026/03/SendEvent.png?v=f6b9e32e877d)

![The Has Received Event Condition listens for the matching name and stores optional values.](https://opsive.com/wp-content/uploads/2026/02/HasReceivedEventCondition.png?v=89fe0673970c)

## How it runs

Waiting remains active until a matching event arrives. Has Received Event records the optional values, allows the transition once, and clears its received flag. React can then face the supplied target, play an animation, update a variable, or perform another finite sequence before returning to Waiting.

Because the Condition is one-shot, a later reaction requires another event. This makes events suitable for occurrences such as a target being spotted, a door being used, or a dialogue line finishing.

## Key choices

- Use a targeted event when one known GameObject should react. Use a global event only when every matching listener should receive the notification.
- Match the event name, targeted/global option, target, argument count, and argument types on both sides.
- Store an event argument in a Shared Variable when several Actions or later states need it.
- Use a normal Shared Variable Condition instead when the receiver needs persistent state rather than a one-time occurrence.

## Verify in Play Mode

Trigger the sender twice. Each send should move Waiting to React exactly once, and any stored event value should contain the sent argument. A misspelled name or mismatched delivery option should leave Waiting active.

## Related pages

- [Events](https://opsive.com/support/documentation/state-designer/events/)
- [Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/)
- [Shared Variables](https://opsive.com/support/documentation/state-designer/concepts/blackboard/)
- [Toggle an Interaction](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/toggle-an-interaction/)

---

<a id="page-state-designer-concepts-common-graphs-toggle-an-interaction"></a>

# Toggle an Interaction

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/toggle-an-interaction/)

Use this graph for a door, switch, platform, or other interaction that has stable states and must finish its transition before accepting the opposite command.

## In the editor

1. Create Closed, Opening, Open, and Closing Action States in a loop.
2. Put **Idle** in Closed and Open so each stable state remains Running.
3. Connect Closed to Opening and Open to Closing. Add **Has Received Event** to both transitions with the same targeted Event Name, such as `Interact`.
4. Configure Opening to play the opening animation and sound. Use **Parallel** Execution Type when both should start together and the state should finish only after both complete.
5. Configure Closing with the corresponding closing Actions.
6. Connect Opening to Open and Closing to Closed with **State Finished**.

The supplied State Designer samples use the reusable `DoorInteract` Subgraph for this kind of animation-and-audio interaction. Keep the state machine on a controller GameObject when an Action may disable the visible object.

## How it runs

Closed waits for the Interact event, then enters Opening. While Opening is active, another event does not take the Open-to-Closing transition because Open is not active yet. After every Opening Action finishes, State Finished enters Open. The next Interact event begins Closing, which completes before returning to Closed.

Separating the stable and in-progress modes prevents overlapping open and close sequences. The active state also gives other systems a clear answer about whether the interaction is closed, moving, or open.

## Key choices

- Use one-shot events for discrete interaction presses. Use a boolean Condition when an external system owns a persistent desired state.
- Choose **Sequence** when animation, sound, and gameplay changes must happen in order. Choose **Parallel** when they should begin together.
- Add an Any-to-Locked or Any-to-Disabled transition when one condition must interrupt both stable states, but decide explicitly whether it may interrupt Opening and Closing.
- Export the interaction as a Subgraph when several doors share the flow, then override animation clips, sounds, and target objects per reference.

## Verify in Play Mode

Send Interact while Closed and confirm the active highlight advances through Opening to Open. Send it again and confirm Open advances through Closing to Closed. Repeated input during an in-progress state should not start the opposite transition early.

## Related pages

- [React to an Event](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/react-to-an-event/)
- [Action State](https://opsive.com/support/documentation/state-designer/concepts/states/action-state/)
- [Subgraphs](https://opsive.com/support/documentation/state-designer/subgraphs/)
- [Select a Reusable Attack Subgraph](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/select-a-reusable-attack-subgraph/)

---

<a id="page-state-designer-concepts-common-graphs-select-a-reusable-attack-subgraph"></a>

# Reusable Attack Subgraph

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/select-a-reusable-attack-subgraph/)

Use this graph when one parent flow should run interchangeable melee, ranged, or other attack behavior without duplicating the surrounding states.

## In the editor

1. Author and test each attack as its own Subgraph. Give the variants the same external inputs where possible, such as Target and Attack Speed.
2. In the parent graph, add a **Subgraph Reference Selector** where the attack mode belongs.
3. Add the Subgraphs to its list in a stable order, such as Melee Attack at index `0` and Pistol Attack at index `1`.
4. Create an integer Shared Variable named Attack Subgraph Index and assign it to **Subgraph Index**.
5. Add Shared Variable Overrides that map the selected Subgraph's inputs to the parent graph's Target and configuration values.
6. Keep **Reevaluate On Index Change** enabled only when changing the variable should rebuild the references and restart the graph automatically.

![A Subgraph Reference maps a source Shared Variable to a value supplied by its parent graph.](https://opsive.com/wp-content/uploads/2026/03/SubgraphReferenceOverride.png?v=57c99a014611)

After importing the samples, the Subgraph Replacement scene and its MeleeAttack and PistolAttack assets provide a concrete version of this pattern.

## How it runs

Before the graph starts, Subgraph Reference Selector reads Attack Subgraph Index and injects the one Subgraph at that list position. The parent graph then runs the selected states and transitions as part of its own flow.

When Reevaluate On Index Change is enabled, changing the index queues reference reevaluation at the end of the frame. State Designer rebuilds the injected content and restarts the graph. Make that change at a safe mode boundary when restarting in-progress behavior would be visible.

## Key choices

- Keep the Subgraph list order stable because the index selects by position.
- Map variables by purpose. Both attack variants can receive the parent's Target even when their internal Actions differ.
- Use an ordinary **Subgraph Reference** when the referenced behavior never changes.
- Split only cohesive behavior into a Subgraph. A tiny one-state asset can be harder to follow than leaving that state in the parent.

## Verify in Play Mode

Start once with index `0` and confirm the melee states are injected and run. Change to index `1` at a safe point and confirm the graph restarts with the pistol states. Verify that both variants receive the same parent Target through their overrides.

## Related pages

- [Subgraphs](https://opsive.com/support/documentation/state-designer/subgraphs/)
- [Subgraph Reference](https://opsive.com/support/documentation/state-designer/concepts/states/subgraph-reference/)
- [Shared Variables](https://opsive.com/support/documentation/state-designer/concepts/blackboard/)
- [Toggle an Interaction](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/toggle-an-interaction/)

---

<a id="page-state-designer-concepts-common-graphs-menu-screen-flow"></a>

# Menu Screen Flow

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/menu-screen-flow/)

Use this graph when exactly one menu screen should be active and button clicks should make the permitted navigation paths explicit.

## In the editor

1. Put the State Machine on a persistent Menu Controller rather than on a panel that the graph will disable.
2. Add Main Menu, Options, and Credits Action States. Connect Start to Main Menu.
3. In each state, use **Set Active** Actions to enable its panel and disable the other panels. Run the setup Actions in Sequence, then finish with **Idle** so the state remains Running.
4. Connect Main Menu to Options and Credits. Add **On Button Clicked** to each transition and assign the matching button GameObject.
5. Connect Options and Credits back to Main Menu with separate On Button Clicked Conditions assigned to their Back buttons.
6. Use **Continuous** evaluation for each button transition.

The supplied UIMenu sample uses State Designer Actions and On Button Clicked Conditions to coordinate UI behavior. Its graph is a useful reference after importing the sample content.

## How it runs

Entering a screen state activates the intended panel, disables the others, and then idles while its outgoing button Conditions listen. A button click is consumed once and activates the destination state. That state's Actions immediately update the visible panels before it begins waiting for the next choice.

Because navigation is represented by connections, the graph also documents which screens are reachable from each current screen. A modal confirmation can be another state with only Confirm and Cancel transitions.

## Key choices

- Keep the State Machine outside every panel it controls. Disabling its own GameObject stops the graph.
- Keep one state per mutually exclusive screen. Use parallel Actions inside a state for independent visual or audio effects that should continue together.
- Use unscaled-time Actions for transitions that must animate while gameplay time is paused.
- Use an Any transition sparingly for a global Close command; ordinary Back transitions preserve the intended navigation rules more clearly.

## Verify in Play Mode

Click Options, Back, Credits, and Back. Confirm that the active highlight follows the same route, exactly one panel remains active after each transition, and a click produces only one state change.

## Related pages

- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)
- [Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/)
- [Any](https://opsive.com/support/documentation/state-designer/concepts/states/any/)
- [React to an Event](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/react-to-an-event/)

---

<a id="page-state-designer-concepts-common-graphs-dialogue-choice-flow"></a>

# Dialogue Choice Flow

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/dialogue-choice-flow/)

Model a short conversation as one prompt State with one transition per visible answer. This keeps response availability, selected outcomes, and UI ownership explicit.

## Build the graph

1. Create an Action State named `Show Question` that enables the question panel and assigns its text.
2. Add `Accept`, `Decline`, and `Ask Later` States for the possible outcomes.
3. Connect Show Question to each response State.
4. Add one UI-button or event Condition to each transition. Give every button or event a unique, stable identifier.
5. In each response State, run the Actions that update dialogue data, quests, reputation, or another project system.
6. Connect every completed response to `Close Dialogue` or back to the owning conversation flow.

## How it runs

Only Show Question listens for the response. Selecting one answer makes its transition valid, exits the question State, and prevents the other outcomes from running. The response State applies its result and then finishes or waits for the next prompt.

If several Conditions read one shared selection index, order the most specific choices first and clear the index when the response is consumed. An event-per-button design avoids a stale selection remaining valid when the same prompt is entered again.

## Key choices

- Keep UI enable/disable work in Actions and yes-or-no selection checks in Conditions.
- Use Shared Variables for the speaker, listener, current line, and selected response only when several States need them.
- Use a Subgraph when many conversations share the same prompt/response lifecycle.
- Keep narrative data in the dialogue system or project model; the graph should coordinate the flow rather than duplicate the complete script.

## Verify in Play Mode

Open the prompt and choose each response in a separate run. Exactly one response State should activate, the other branches should remain inactive, and reopening the prompt should not automatically reuse the prior answer.

## Troubleshooting

| Symptom | Check | Fix |
| --- | --- | --- |
| Two responses run. | Shared input event, Condition Mode, and transition order. | Give each response a unique event or value and consume it once. |
| The old response runs on reopen. | Stored selection or unconsumed event. | Clear the value on entry or after the transition. |
| The UI closes before a click is read. | Action completion and transition evaluation timing. | Keep Show Question active until a response Condition becomes valid. |

## Related pages

- [Menu Screen Flow](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/menu-screen-flow/)
- [React to an Event](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/react-to-an-event/)
- [Variables](https://opsive.com/support/documentation/state-designer/variables/)
- [Transition Evaluation and Priority](https://opsive.com/support/documentation/state-designer/concepts/transition-evaluation-and-priority/)

---

<a id="page-state-designer-concepts-common-graphs-turn-based-phase-loop"></a>

# Turn-Based Phase Loop

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/turn-based-phase-loop/)

Alternate player and opponent control through explicit phases so only one side can act and each turn has one visible completion boundary.

## Build the graph

1. Add `Begin Round`, `Player Turn`, `Resolve Player`, `Opponent Turn`, `Resolve Opponent`, and `End Round` States.
2. Use Actions on Begin Round to reset per-round counters and choose the starting side.
3. Keep Player Turn active while player input is accepted. Transition on a submitted action or end-turn event.
4. Resolve the submitted action in Resolve Player, then transition to Opponent Turn when its Actions finish.
5. Let Opponent Turn run the AI decision. Transition after one committed decision, not every state-machine tick.
6. Resolve the opponent action, then either begin the next round or enter End Round when the victory Condition is valid.

## How it runs

The current phase owns input and decision-making. Resolution States apply animation, damage, movement, and other consequences without allowing the next side to act early. The loop ends only through the victory route.

For a manually ticked design, the game owner decides when to tick the State Machine and may limit how many States activate per tick. Keep that scheduling outside individual Actions so the turn boundary remains testable.

## Key choices

- Use an event or explicit `ActionSubmitted` value to leave Player Turn.
- Store the chosen move before leaving the decision State.
- Do not keep both player and opponent input enabled and rely only on UI visibility.
- Put victory checks before the ordinary next-turn transition.

## Verify in Play Mode

Submit one player action and confirm that input disables, its result completes, the opponent chooses exactly once, and control returns to the player. Force a victory during each resolution phase and confirm that End Round wins over the next-turn route.

## Troubleshooting

| Symptom | Check | Fix |
| --- | --- | --- |
| Both sides act. | Input ownership and phase activation. | Enable only the current phase's controller or input Actions. |
| The opponent acts repeatedly. | Manual ticking and completion event. | Stop after one committed decision and wait for resolution. |
| A completed match starts another turn. | Transition priority. | Put the victory route before the normal loop transition. |

## Related pages

- [Transition Evaluation and Priority](https://opsive.com/support/documentation/state-designer/concepts/transition-evaluation-and-priority/)
- [Events](https://opsive.com/support/documentation/state-designer/events/)
- [Save and Resume a State Machine](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/save-and-resume-a-state-machine/)
- [API](https://opsive.com/support/documentation/state-designer/api/)

---

<a id="page-state-designer-concepts-common-graphs-save-and-resume-a-state-machine"></a>

# Save and Resume a State Machine

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/save-and-resume-a-state-machine/)

Save a state machine only after defining which graph state, Shared Variables, and external gameplay data must survive. Restore those owners together and verify the same active flow resumes.

## Choose the saved boundary

For a simple checkpoint, preserve:

- the active State and the graph's supported runtime data;
- Shared Variables that represent durable progress;
- the owner's Transform or other project data when the graph depends on it; and
- external Animator, inventory, quest, or scene data through the system that owns it.

Do not assume that saving the graph also serializes every referenced Component or asset.

## Build the flow

1. Add a durable checkpoint State such as `Exploring` or `Player Turn`.
2. Save only after entry Actions have established a stable value set.
3. Route the save command through the project save owner or the State Designer save API described on [Save/Load](https://opsive.com/support/documentation/state-designer/save-load/).
4. On load, create or locate the correct owner before restoring graph data.
5. Restore external data in a documented order, then allow the graph to continue.

## How it runs

A correct load returns to the intended State with the variables and external systems it expects. A load taken during a short transition or partially completed Action may require project-specific resumption logic; prefer stable checkpoints for the first implementation.

## Verify in Play Mode

Save while a distinctive State is active and set one Shared Variable to a recognizable value. Change both the State and value, then load. Confirm that the original State and value return and that the next transition behaves as it did before saving. Repeat after reloading the scene when the production save must survive scene changes.

## Troubleshooting

| Symptom | Check | Fix |
| --- | --- | --- |
| The State restores but gameplay data does not. | External system ownership. | Save and restore that data through its owning system. |
| Load finds no state machine. | Owner creation and identifier timing. | Create/register the owner before applying graph data. |
| A restored State immediately exits. | Restored Condition inputs and Evaluation Mode. | Restore dependent values before resuming evaluation. |

## Related pages

- [Save/Load](https://opsive.com/support/documentation/state-designer/save-load/)
- [Persistent State Across Scenes](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/persistent-state-across-scenes/)
- [Variables](https://opsive.com/support/documentation/state-designer/variables/)
- [Transition Evaluation and Priority](https://opsive.com/support/documentation/state-designer/concepts/transition-evaluation-and-priority/)

---

<a id="page-state-designer-concepts-common-graphs-persistent-state-across-scenes"></a>

# Persistent State Across Scenes

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/persistent-state-across-scenes/)

Keep one state-machine owner alive across scene changes while treating scene objects as replaceable references that must be rebound after each load.

## Build the ownership model

1. Choose one persistent GameObject to own the State Machine.
2. Mark that owner with the project's persistent-object lifecycle, such as `DontDestroyOnLoad`.
3. Ensure only one copy exists after loading another scene.
4. Store durable values in Graph, GameObject, or Project scope according to their real lifetime.
5. Rebind scene-local objects after the new scene loads instead of retaining destroyed references.

The imported Persistent Scenes A and B samples demonstrate one owner moving between two scenes. Add both scenes to the build list before testing the sample route.

## How it runs

The active State and persistent variables remain with the owner. References to scene-only targets, cameras, UI, spawn points, or managers may become invalid when the old scene unloads. A scene-loaded Action, event, or project coordinator should supply the replacement references before Conditions use them.

## Verify in Play Mode

Enter a distinctive State, change one persistent variable, and load the second scene. Confirm that there is still exactly one owner, the State and value remain, scene references point into the new scene, and returning to the first scene does not create a duplicate owner.

## Troubleshooting

| Symptom | Check | Fix |
| --- | --- | --- |
| Two machines run after a scene load. | Persistent owner plus a scene copy. | Use one creation authority and reject duplicates. |
| The machine persists but throws missing-reference errors. | Scene-local object references. | Rebind after scene load before evaluation resumes. |
| State resets on every scene. | Owner lifetime and initialization code. | Keep the same owner and avoid reinitializing an already restored machine. |

## Related pages

- [Save and Resume a State Machine](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/save-and-resume-a-state-machine/)
- [Referencing Scene Objects](https://opsive.com/support/documentation/state-designer/referencing-scene-objects/)
- [Save/Load](https://opsive.com/support/documentation/state-designer/save-load/)
- [Events](https://opsive.com/support/documentation/state-designer/events/)

---

<a id="page-state-designer-concepts-common-graphs-animation-driven-locomotion"></a>

# Animation-Driven Locomotion

[View this page online](https://opsive.com/support/documentation/state-designer/concepts/common-graphs/animation-driven-locomotion/)

Represent durable movement modes as States while keeping Animator updates and movement work in focused Actions. This prevents animation parameters, navigation, and physical movement from competing for ownership.

## Build the graph

1. Add `Idle`, `Move`, `Jump`, and `Land` States appropriate to the controller.
2. In Idle and Move, use Actions that update the Animator values required by the project's controller.
3. Let the existing movement owner—Character Controller, NavMeshAgent, Rigidbody, or project motor—apply translation.
4. Put input, grounded, speed, and completion checks on transitions as Conditions.
5. Use Jump and Land only when those are durable modes with distinct entry, update, or completion behavior.

## How it runs

State Designer selects the locomotion mode. Actions translate authoritative movement data into Animator parameters and request work from the movement system. The Animator presents the result; it does not become a second decision system unless root motion intentionally owns translation.

The Animation Sync sample converts NavMeshAgent velocity into the float parameter expected by its sample Animator Controller. A production controller needs a matching script or Actions for its own parameter names and blend-tree structure.

## Key choices

- Use one movement authority. Do not move the Transform directly while a Rigidbody, Character Controller, or NavMeshAgent also owns it.
- Decide explicitly whether root motion or code supplies position and rotation.
- Keep short animation clips inside a durable State only when their completion controls the transition.
- Use Shared Variables for speed, grounded state, or requested direction when both Actions and Conditions need the same authoritative values.

## Verify in Play Mode

Move from idle to locomotion, jump or trigger another transient mode, then return to idle. Confirm that the active State, Animator parameters, visible clip, and physical movement agree throughout the cycle. Stop one movement input and verify that no second system continues moving the object.

## Troubleshooting

| Symptom | Check | Fix |
| --- | --- | --- |
| Animation changes but the object does not move. | Movement authority and root-motion choice. | Supply movement through the configured controller or enable the intended root motion. |
| The object jitters or moves twice. | Competing Transform, Rigidbody, NavMeshAgent, and root-motion paths. | Keep one translation owner and let the graph request rather than duplicate movement. |
| The State and animation disagree. | Parameter update order and transition inputs. | Derive both from the same authoritative movement data. |

## Related pages

- [Built-in Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/built-in-actions/)
- [Built-in Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/built-in-conditions/)
- [Variables](https://opsive.com/support/documentation/state-designer/variables/)
- [Transition Evaluation and Priority](https://opsive.com/support/documentation/state-designer/concepts/transition-evaluation-and-priority/)

---

<a id="page-state-designer-new-nodes"></a>

# New Nodes

[View this page online](https://opsive.com/support/documentation/state-designer/new-nodes/)

Built-in Actions and Conditions cover many common situations. Create a custom node when a state needs project-specific behavior, when a transition needs a rule that is unique to your game, or when State Designer must work with another system in your project.

Create an Action when something should happen while a state is active. Create a Condition when a transition needs a yes-or-no check before it can move to another state.

## Choose a workflow

Use the GameObject workflow for most custom nodes. It is the most direct option for working with scene objects, existing Unity components, and familiar gameplay code.

Use the Entity workflow when the project already relies on ECS or profiling shows that the custom logic must scale across many entities. A project can use both workflows, so you can start with GameObject nodes and move only performance-sensitive behavior to Entity nodes later.

## GameObject nodes

- [GameObject Action](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-action/) — Create behavior that runs inside an Action State, such as movement, animation, audio, or interaction logic.
- [GameObject Condition](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-condition/) — Create a transition check based on scene objects, component values, input, or other game-specific rules.

## Entity nodes

- [Entity Action](https://opsive.com/support/documentation/state-designer/new-nodes/entity-action/) — Create state behavior that can be processed through an ECS workflow across many entities.
- [Entity Condition](https://opsive.com/support/documentation/state-designer/new-nodes/entity-condition/) — Create transition checks that use ECS data and execution.

---

<a id="page-state-designer-new-nodes-gameobject-action"></a>

# GameObject Action

[View this page online](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-action/)

Create a custom GameObject Action when an Action State needs to perform project-specific work that the built-in Actions do not provide. This is the usual workflow for behavior that works with scene objects and Unity components, such as a movement rule, animation command, sound, or interaction.

Start with a GameObject Action unless profiling shows that this behavior needs an ECS implementation for a large number of entities.

## Create the Action

1. Create a C# script for one focused behavior. The example on this page uses `MoveTowardsRandomPoint`.
2. Derive the class from `Opsive.StateDesigner.Runtime.Actions.Action`.
3. Add serialized fields for the values that should be configurable in the editor. Use Shared Variables when another Action or state should share those values.
4. Use `OnStart` for setup that should happen when the Action begins.
5. Implement `OnUpdate` and return `StateStatus.Running` while the work continues or `StateStatus.Finished` when it is complete.
6. Let Unity compile the script before opening the Action selector.

The complete movement example appears later on this page, after the editor workflow and optional APIs.

## Add and configure the Action in the editor

1. Add or select an **Action State** in the graph.
2. In the Element Inspector, use the Actions list's add control and search for **Move Towards Random Point**.
3. Select the Action from the **Movement** category. The example's `Category` attribute places it there, while its `Description` and `NodeIcon` attributes provide editor details.
4. Configure **Center**, **Radius**, **Move Speed**, and **Arrive Distance**. Each field can use its local value or a compatible Shared Variable.
5. Choose the Action State's Sequence or Parallel execution type according to the other Actions in that state.

After it is added, the custom Action appears in the Action State's ordered Actions list and can be reused in other Action States with different values.

## How it runs

When the Action starts, `MoveTowardsRandomPoint` chooses a destination within the configured radius around Center. During each update, it moves the GameObject toward that destination and returns `Running`.

When the GameObject comes within Arrive Distance, the Action returns `Finished`. In a Sequence, the Action State can then continue to its next Action. In Parallel, the Action State waits for its other enabled Actions to finish as well.

## Lifecycle callbacks

A custom GameObject Action derives from `Opsive.StateDesigner.Runtime.Actions.Action`. Override only the callbacks that the behavior needs:

```csharp
/// <summary>
/// Callback when the state machine is initialized.
/// </summary>
public virtual void OnAwake()

/// <summary>
/// Callback when the state machine is started.
/// </summary>
public virtual void OnStateMachineStarted()

/// <summary>
/// Callback when the action is started.
/// </summary>
public virtual void OnStart()

/// <summary>
/// Executes the action logic.
/// </summary>
/// <returns>The status of the action.</returns>
public virtual StateStatus OnUpdate()

/// <summary>
/// Callback when the action stops.
/// </summary>
public virtual void OnEnd()

/// <summary>
/// Callback when the state machine is stopped.
/// </summary>
/// <param name="pause">Is the state machine paused?</param>
public virtual void OnStateMachineStopped(bool pause)

/// <summary>
/// Callback when the state machine is destroyed.
/// </summary>
public virtual void OnDestroy()
```

## Physics callbacks

For performance, physics callbacks are only registered when needed. Override the corresponding receive property with `true`:

- `ReceiveCollisionEnterCallback`
- `ReceiveCollisionExitCallback`
- `ReceiveCollisionEnter2DCallback`
- `ReceiveCollisionExit2DCallback`
- `ReceiveTriggerEnterCallback`
- `ReceiveTriggerExitCallback`
- `ReceiveTriggerEnter2DCallback`
- `ReceiveTriggerExit2DCallback`
- `ReceiveControllerColliderHitCallback`

Then implement the matching callback method, such as `OnTriggerEnter` or `OnCollisionEnter`.

## Save and load

Add save and load support only when the Action has runtime state that must survive a save. The available API is:

```csharp
/// <summary>
/// Specifies the type of reflection that should be used to save the action.
/// </summary>
/// <param name="index">The index of the sub-action.</param>
public virtual MemberVisibility GetSaveReflectionType(int index)

/// <summary>
/// Returns the current action state.
/// </summary>
/// <param name="world">The DOTS world.</param>
/// <param name="entity">The DOTS entity.</param>
/// <returns>The current action state.</returns>
public virtual object Save(World world, Entity entity)

/// <summary>
/// Loads the previous action state.
/// </summary>
/// <param name="saveData">The previous action state.</param>
/// <param name="world">The DOTS world.</param>
/// <param name="entity">The DOTS entity.</param>
public virtual void Load(object saveData, World world, Entity entity)
```

Choose the reflection behavior with `MemberVisibility`:

- **MemberVisibility.All:** Save public and private fields through reflection.
- **MemberVisibility.Public:** Save public and serialized private fields through reflection.
- **MemberVisibility.None:** Do not save fields through reflection. Implement `Save` and `Load` manually.

## Complete example: Move Towards a Random Point

This Action chooses a random destination in a radius around a center, moves toward it, and finishes once it arrives. It also saves and restores the chosen destination.

```csharp
using Opsive.GraphDesigner.Runtime;
using Opsive.GraphDesigner.Runtime.Variables;
using Opsive.Shared.Utility;
using Opsive.StateDesigner.Runtime.Actions;
using Opsive.StateDesigner.Runtime.States;
using Unity.Entities;
using UnityEngine;

[Category("Movement")]
[Description("Moves the agent towards a random position within the specified radius.")]
[NodeIcon("Assets/MyIcon.png")]
public class MoveTowardsRandomPoint : Action
{
    [Tooltip("The center point of the random position.")]
    [SerializeField] protected SharedVariable<Vector3> m_Center;
    [Tooltip("The radius that contains the random position.")]
    [SerializeField] protected SharedVariable<float> m_Radius = 10f;
    [Tooltip("The speed that the agent should move towards the destination.")]
    [SerializeField] protected SharedVariable<float> m_MoveSpeed = 5f;
    [Tooltip("Distance threshold used to consider the destination reached.")]
    [SerializeField] protected SharedVariable<float> m_ArriveDistance = 0.5f;

    private Vector3 m_Destination;

    /// <summary>
    /// Callback when the action is started.
    /// </summary>
    public override void OnStart()
    {
        m_Destination = m_Center.Value + Random.insideUnitSphere * Random.Range(0f, m_Radius.Value);
    }

    /// <summary>
    /// Executes the action logic.
    /// </summary>
    /// <returns>The status of the action.</returns>
    public override StateStatus OnUpdate()
    {
        if (Vector3.Distance(transform.position, m_Destination) <= m_ArriveDistance.Value) {
            return StateStatus.Finished;
        }

        transform.position = Vector3.MoveTowards(transform.position, m_Destination, m_MoveSpeed.Value * Time.deltaTime);
        return StateStatus.Running;
    }

    /// <summary>
    /// Specifies the type of reflection that should be used to save the action.
    /// </summary>
    public override MemberVisibility GetSaveReflectionType(int index)
    {
        // Save manually.
        return MemberVisibility.None;
    }

    /// <summary>
    /// Returns the current action state.
    /// </summary>
    public override object Save(World world, Entity entity)
    {
        return m_Destination;
    }

    /// <summary>
    /// Loads the previous action state.
    /// </summary>
    public override void Load(object saveData, World world, Entity entity)
    {
        m_Destination = (Vector3)saveData;
    }
}
```

## Verify in Play Mode

Add `MoveTowardsRandomPoint` to an Action State on a GameObject, assign Center, and use visible Radius, Move Speed, and Arrive Distance values. Enter Play Mode and activate that state.

Confirm that the Action is highlighted while the GameObject moves and that the GameObject stops within Arrive Distance of its chosen destination. When the Action finishes, the highlight should clear; a Sequence can then start its next Action, and a transition configured for state completion can leave the state. If the Action is not available in the selector, first resolve any script compilation errors and confirm that the class derives from the State Designer `Action` type.

## Related pages

- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/) explains the role of Actions in a state machine.
- [Action State](https://opsive.com/support/documentation/state-designer/concepts/states/action-state/) shows where GameObject Actions are added and how their execution order works.
- [Accessing Variables](https://opsive.com/support/documentation/state-designer/variables/accessing-variables/) shows how custom Actions use Shared Variables.
- [Save and Load](https://opsive.com/support/documentation/state-designer/save-load/) explains state-machine persistence.
- [GameObject Condition](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-condition/) covers custom transition checks.
- [Entity Action](https://opsive.com/support/documentation/state-designer/new-nodes/entity-action/) covers the ECS authoring workflow.

---

<a id="page-state-designer-new-nodes-gameobject-condition"></a>

# GameObject Condition

[View this page online](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-condition/)

Create a GameObject Condition when a transition needs a game-specific yes-or-no check based on scene objects, Unity components, input, or other familiar gameplay code. This is the recommended custom Condition workflow unless profiling shows that the check needs ECS-specific optimization.

## Add the Condition to a transition

1. Create a class that derives from `Opsive.StateDesigner.Runtime.Conditions.Condition`.
2. Implement `IsValid()` so the Condition reports whether the transition is currently allowed.
3. After Unity compiles the script, select the transition in the State Designer graph.
4. Add the new Condition from the Conditions list in the Element Inspector.
5. Configure its serialized fields for that transition. The HasEnteredTrigger example below exposes an optional Tag filter.

The custom Condition appears as a reusable choice on transitions. It does not perform the gameplay behavior itself; it only reports whether its rule is valid.

## How it runs

State Designer evaluates the Condition according to the transition's Evaluation Mode. When `IsValid()` returns true, the Condition allows that transition to proceed if its other configured requirements are also satisfied.

In the included HasEnteredTrigger example, `OnStart()` clears the previous result. A matching trigger sets the result to true, and `IsValid()` returns that stored result. Leaving the Tag empty accepts any trigger.

## Verify the Condition

1. Add HasEnteredTrigger to a transition and optionally set its Tag.
2. Enter Play Mode while the transition's source State is active.
3. Enter the trigger with a matching GameObject and confirm that the transition can occur.
4. If a Tag is configured, enter with a nonmatching GameObject and confirm that the Condition remains invalid.

## GameObject Condition API

A custom condition can implement the following callbacks:

```csharp
/// <summary>
/// Callback when the state machine is initialized.
/// </summary>
public virtual void OnAwake()

/// <summary>
/// Callback when the state machine is started.
/// </summary>
public virtual void OnStateMachineStarted()

/// <summary>
/// Callback when the condition starts.
/// </summary>
public virtual void OnStart()

/// <summary>
/// Is the condition valid? If it is valid then the transition will occur.
/// </summary>
/// <returns>True if the condition is valid.</returns>
public abstract bool IsValid()

/// <summary>
/// Callback when the condition stops.
/// </summary>
public virtual void OnEnd()

/// <summary>
/// Callback when the state machine is stopped.
/// </summary>
/// <param name="pause">Is the state machine paused?</param>
public virtual void OnStateMachineStopped(bool pause)

/// <summary>
/// Callback when the state machine is destroyed.
/// </summary>
public virtual void OnDestroy()
```

## Physics callbacks

Physics callbacks are opt-in for efficiency. If your Condition needs one, override the corresponding receive property with `true`:

-   ReceiveCollisionEnterCallback
-   ReceiveCollisionExitCallback
-   ReceiveCollisionEnter2DCallback
-   ReceiveCollisionExit2DCallback
-   ReceiveTriggerEnterCallback
-   ReceiveTriggerExitCallback
-   ReceiveTriggerEnter2DCallback
-   ReceiveTriggerExit2DCallback
-   ReceiveControllerColliderHitCallback

Then implement the matching callback method, such as `OnTriggerEnter` or `OnCollisionEnter`.

## Save/Load API

Conditions support runtime save/load:

```csharp
/// <summary>
/// Specifies the type of reflection that should be used to save the action.
/// </summary>
/// <param name="index">The index of the sub-action.</param>
public virtual MemberVisibility GetSaveReflectionType(int index)

/// <summary>
/// Returns the current action state.
/// </summary>
/// <param name="world">The DOTS world.</param>
/// <param name="entity">The DOTS entity.</param>
/// <returns>The current action state.</returns>
public virtual object Save(World world, Entity entity)

/// <summary>
/// Loads the previous action state.
/// </summary>
/// <param name="saveData">The previous action state.</param>
/// <param name="world">The DOTS world.</param>
/// <param name="entity">The DOTS entity.</param>
public virtual void Load(object saveData, World world, Entity entity)
```

MemberVisibility options:

-   _MemberVisibility.All:_ Save public and private fields via reflection.
-   _MemberVisibility.Public:_ Save public and serialized private fields via reflection.
-   _MemberVisibility.None:_ No reflection-based save. Implement Save and Load manually.

## Example: HasEnteredTrigger

This Condition returns `true` after a matching trigger is entered.

```csharp
using Opsive.GraphDesigner.Runtime;
using Opsive.GraphDesigner.Runtime.Variables;
using Opsive.Shared.Utility;
using Opsive.StateDesigner.Runtime.Conditions;
using Unity.Entities;
using UnityEngine;

[Description("Returns true after a matching trigger is entered.")]
public class HasEnteredTrigger : Condition
{
    [Tooltip("Optional tag filter. Leave empty to accept any trigger.")]
    [SerializeField] protected SharedVariable<string> m_Tag;

    private bool m_EnteredTrigger;

    protected override bool ReceiveTriggerEnterCallback => true;

    /// <summary>
    /// Callback when the condition starts.
    /// </summary>
    public override void OnStart()
    {
        m_EnteredTrigger = false;
    }

    /// <summary>
    /// Is the condition valid?
    /// </summary>
    public override bool IsValid()
    {
        return m_EnteredTrigger;
    }

    /// <summary>
    /// Trigger enter callback.
    /// </summary>
    protected override void OnTriggerEnter(Collider other)
    {
        if (!string.IsNullOrEmpty(m_Tag.Value) && !other.gameObject.CompareTag(m_Tag.Value)) {
            return;
        }

        m_EnteredTrigger = true;
    }

    /// <summary>
    /// Save manually.
    /// </summary>
    public override MemberVisibility GetSaveReflectionType(int index)
    {
        return MemberVisibility.None;
    }

    public override object Save(World world, Entity entity)
    {
        return m_EnteredTrigger;
    }

    public override void Load(object saveData, World world, Entity entity)
    {
        m_EnteredTrigger = (bool)saveData;
    }
}
```

## Related pages

- [Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/)
- [States](https://opsive.com/support/documentation/state-designer/concepts/states/)
- [New Nodes](https://opsive.com/support/documentation/state-designer/new-nodes/)
- [GameObject Action](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-action/)
- [Entity Condition](https://opsive.com/support/documentation/state-designer/new-nodes/entity-condition/)
- [Save/Load](https://opsive.com/support/documentation/state-designer/save-load/)

---

<a id="page-state-designer-new-nodes-entity-action"></a>

# Entity Action

[View this page online](https://opsive.com/support/documentation/state-designer/new-nodes/entity-action/)

An Entity Action runs State Designer behavior through ECS systems and jobs. Use one when the project already uses ECS or when profiling shows that an Action must scale across many entities. For ordinary scene-object behavior, a [GameObject Action](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-action/) is usually the simpler starting point.

## In the editor

An Entity Action appears as its own state node rather than as a GameObject Action inside an Action State. After the example class compiles, open **Create State**, choose **Move To Point** from the **Documentation/ECS** category, and place it in the graph.

Select the node to configure **Target**, **Speed**, and **Arrive Distance** in the Element Inspector. These fields come from the serialized values on the authoring class; State Designer converts them to ECS data when it initializes the graph.

## Authoring workflow

An ECS action in State Designer is made of four parts:

1. An authoring Action class that appears in the editor.
2. A runtime buffer component containing the per-entity values.
3. An enableable flag identifying when this Action is active.
4. A system, with an optional job, that performs the runtime work.

### Authoring Action class

This is the class you add in the graph editor. It stores inspector values and converts them into runtime ECS data. You derive from:

```csharp
ECSAction<TSystem, TBufferElement, TComponentFlag>
```

and implement `GetBufferElement()`.

```csharp
using Opsive.StateDesigner.Runtime.States;
using Unity.Entities;
using UnityEngine;

[Opsive.Shared.Utility.Category("Documentation/ECS")]
[Opsive.Shared.Utility.Description("Moves the entity to a target point.")]
public class MoveToPoint : ECSAction<MoveToPointSystem, MoveToPointComponent, MoveToPointFlag>
{
    [SerializeField] protected Vector3 m_Target = new Vector3(0, 0, 10);
    [SerializeField] protected float m_Speed = 5f;
    [SerializeField] protected float m_ArriveDistance = 0.25f;

    /// <summary>
    /// Creates the runtime ECS buffer element used by the action system.
    /// </summary>
    /// <returns>The initialized action buffer data.</returns>
    public override MoveToPointComponent GetBufferElement()
    {
        return new MoveToPointComponent {
            // RuntimeIndex maps this action to its StateComponent.
            Index = RuntimeIndex,
            Target = m_Target,
            Speed = m_Speed,
            ArriveDistance = m_ArriveDistance
        };
    }
}
```

### Runtime buffer component

This is the runtime data your system reads/writes.

```csharp
using Unity.Entities;
using Unity.Mathematics;

/// <summary>
/// Runtime ECS data for MoveToPoint.
/// </summary>
public struct MoveToPointComponent : IBufferElementData
{
    public ushort Index;
    public float3 Target;
    public float Speed;
    public float ArriveDistance;
}
```

The `Index` field maps to a `StateComponent` entry, and that entry holds the Action execution status (`Queued`, `Running`, `Finished`, and so on). `Index` is the lookup key.

### Active flag

This flag is how State Designer enables/disables your action system per entity/state activity.

```csharp
using Unity.Entities;

/// <summary>
/// ECS enableable tag indicating MoveToPoint is active.
/// </summary>
public struct MoveToPointFlag : IComponentData, IEnableableComponent { }
```

Your Action runs only when this flag and `EvaluateFlag` are both active for the entity.

### System and job

The system executes runtime logic for entities matching your query. Usually this means `StateComponent` plus the Action buffer, any additional data, the Action flag, and `EvaluateFlag`.

```csharp
using Opsive.StateDesigner.Runtime.Components;
using Opsive.StateDesigner.Runtime.States;
using Unity.Burst;
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;

[DisableAutoCreation]
public partial struct MoveToPointSystem : ISystem
{
    private EntityQuery m_Query;

    /// <summary>
    /// Builds and caches the entity query used by this action.
    /// </summary>
    /// <param name="state">The current ECS system state.</param>
    [BurstCompile]
    private void OnCreate(ref SystemState state)
    {
        m_Query = SystemAPI.QueryBuilder().WithAll<MoveToPointFlag, EvaluateFlag>().WithAll<StateComponent, MoveToPointComponent, LocalTransform>().Build();
    }

    /// <summary>
    /// Schedules the action job for matching entities.
    /// </summary>
    /// <param name="state">The current ECS system state.</param>
    [BurstCompile]
    private void OnUpdate(ref SystemState state)
    {
        state.Dependency = new MoveToPointJob {
            DeltaTime = SystemAPI.Time.DeltaTime
        }.ScheduleParallel(m_Query, state.Dependency);
    }

    /// <summary>
    /// Job that executes movement and state status transitions.
    /// </summary>
    [BurstCompile]
    private partial struct MoveToPointJob : IJobEntity
    {
        public float DeltaTime;

        /// <summary>
        /// Executes action logic for a single entity's buffers.
        /// </summary>
        /// <param name="stateComponents">State status buffer for the graph.</param>
        /// <param name="actionComponents">Action runtime data buffer.</param>
        /// <param name="transform">Entity transform.</param>
        [BurstCompile]
        public void Execute(ref DynamicBuffer<StateComponent> stateComponents, ref DynamicBuffer<MoveToPointComponent> actionComponents, RefRW<LocalTransform> transform)
        {
            for (int i = 0; i < actionComponents.Length; ++i) {
                var action = actionComponents[i];
                var stateComponent = stateComponents[action.Index];

                if (stateComponent.Status == StateStatus.Inactive || stateComponent.Status == StateStatus.Finished) {
                    continue;
                }

                if (stateComponent.Status == StateStatus.Queued) {
                    stateComponent.Status = StateStatus.Running;
                    stateComponents[action.Index] = stateComponent;
                }

                if (stateComponent.Status != StateStatus.Running) {
                    continue;
                }

                var currentPos = transform.ValueRO.Position;
                var toTarget = action.Target - currentPos;
                var arriveDistSq = action.ArriveDistance * action.ArriveDistance;

                if (math.lengthsq(toTarget) <= arriveDistSq) {
                    stateComponent.Status = StateStatus.Finished;
                    stateComponents[action.Index] = stateComponent;
                    continue;
                }

                var dir = math.normalizesafe(toTarget);
                var t = transform.ValueRW;
                t.Position += dir * action.Speed * DeltaTime;
                transform.ValueRW = t;
            }
        }
    }
}
```

## How it runs

When State Designer initializes the graph, `GetBufferElement()` copies the editor values into a `MoveToPointComponent` in the entity's dynamic buffer. `RuntimeIndex` links that component to the corresponding `StateComponent`, which stores the Action's execution status.

State Designer enables `MoveToPointFlag` when the node is active. The system query also requires `EvaluateFlag`, the state-status buffer, the Action buffer, and `LocalTransform`, so the job runs only for entities with the required State Designer data.

The job changes a queued Action to Running, moves the entity toward its target, and changes the status to Finished after it reaches the arrival distance. State Designer can then follow an outgoing transition from the completed node.

## Verify the result

After the scripts compile, confirm that:

- **Move To Point** is available in **Create State** under **Documentation/ECS**.
- Selecting the node shows Target, Speed, and Arrive Distance in the Element Inspector.
- In Play mode, an entity enters Running, moves toward the configured target, and reaches Finished within the arrival distance.

If the node appears but does not run, confirm that the system query includes `MoveToPointFlag`, `EvaluateFlag`, `StateComponent`, `MoveToPointComponent`, and `LocalTransform`, and that the job writes status changes back to the `StateComponent` buffer.

## Related pages

- [New Nodes](https://opsive.com/support/documentation/state-designer/new-nodes/)
- [GameObject Action](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-action/)
- [Entity Condition](https://opsive.com/support/documentation/state-designer/new-nodes/entity-condition/)
- [Entity Variables](https://opsive.com/support/documentation/state-designer/variables/entity/)
- [Entity Baking](https://opsive.com/support/documentation/state-designer/entity-baking/)

---

<a id="page-state-designer-new-nodes-entity-condition"></a>

# Entity Condition

[View this page online](https://opsive.com/support/documentation/state-designer/new-nodes/entity-condition/)

Create an Entity Condition when a transition check needs to run through Unity's ECS workflow. It is suited to projects that already use ECS or checks that profiling shows must scale across many entities. For an ordinary scene-object check, a [GameObject Condition](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-condition/) is usually the simpler starting point.

## Add the Condition to a transition

After the example scripts compile, select a transition in the graph and add **Within Distance ECS Condition** from the **Documentation/ECS** category in the Element Inspector. The Condition appears as a reusable transition choice, with **Origin**, **Target**, and **Distance** fields taken from the serialized values on its authoring class.

Configure those fields to describe the distance check. The Condition reports whether that check is valid; it does not change states or perform gameplay work directly.

## Authoring workflow

An Entity Condition has four parts:

1. An authoring Condition class that appears in the editor.
2. A runtime buffer component containing the condition values.
3. An enableable flag identifying when the Condition is active.
4. A system, with an optional job, that evaluates the runtime data.

Unlike a GameObject Condition, an Entity Condition does not return a `bool` from `IsValid()`. Its ECS system increments `TransitionComponent.ValidConditionCount` when the check is true.

### Authoring Condition class

This class stores the fields shown in the Element Inspector and builds runtime condition data for a specific transition index.

```csharp
using Opsive.StateDesigner.Runtime.Conditions;
using Unity.Entities;
using UnityEngine;

/// <summary>
/// Returns valid when the origin is within distance of the target.
/// </summary>
[Opsive.Shared.Utility.Category("Documentation/ECS")]
[Opsive.Shared.Utility.Description("Returns valid when origin is within distance of target.")]
public class WithinDistanceECSCondition : ECSCondition<WithinDistanceECSConditionSystem, WithinDistanceECSConditionComponent, WithinDistanceECSConditionFlag>
{
    [Tooltip("Origin position.")]
    [SerializeField] protected Vector3 m_Origin;
    [Tooltip("Target position.")]
    [SerializeField] protected Vector3 m_Target;
    [Tooltip("Distance threshold.")]
    [SerializeField] protected float m_Distance = 5f;

    /// <summary>
    /// Creates runtime ECS data for this condition and transition.
    /// </summary>
    /// <param name="transitionIndex">The transition buffer index this condition belongs to.</param>
    /// <returns>The initialized condition buffer data.</returns>
    public override WithinDistanceECSConditionComponent GetBufferElement(ushort transitionIndex)
    {
        return new WithinDistanceECSConditionComponent
        {
            TransitionIndex = transitionIndex,
            Origin = m_Origin,
            Target = m_Target,
            Distance = m_Distance
        };
    }

    /// <summary>
    /// Resets inspector values to defaults.
    /// </summary>
    public override void Reset()
    {
        base.Reset();
        m_Origin = Vector3.zero;
        m_Target = Vector3.zero;
        m_Distance = 5f;
    }
}
```

This is the class added in the Element Inspector. It prepares data rather than evaluating the Condition itself. The `transitionIndex` identifies the transition entry that the system must update.

### Runtime buffer component

This struct is the runtime data the Condition system reads.

```csharp
using Unity.Entities;
using Unity.Mathematics;

/// <summary>
/// Runtime ECS data for WithinDistanceECSCondition.
/// </summary>
public struct WithinDistanceECSConditionComponent : IBufferElementData
{
    public ushort TransitionIndex;
    public float3 Origin;
    public float3 Target;
    public float Distance;
}
```

`TransitionIndex` maps this Condition entry to the correct `TransitionComponent` in the entity's transition buffer.

### Active flag

This enableable tag controls when the Condition system processes the entity.

```csharp
/// <summary>
/// ECS enableable tag indicating WithinDistanceECSCondition is active.
/// </summary>
public struct WithinDistanceECSConditionFlag : IComponentData, IEnableableComponent { }
```

### System and job

The Condition system runs in `ConditionSystemGroup`. When the runtime data is valid, it increments `transition.ValidConditionCount`.

```csharp
using Opsive.StateDesigner.Runtime.Components;
using Opsive.StateDesigner.Runtime.Groups;
using Opsive.StateDesigner.Runtime.States;
using Opsive.StateDesigner.Runtime.Transitions;
using Unity.Burst;
using Unity.Entities;
using Unity.Mathematics;

/// <summary>
/// Runtime system for WithinDistanceECSCondition.
/// </summary>
[DisableAutoCreation]
[UpdateInGroup(typeof(ConditionSystemGroup))]
public partial struct WithinDistanceECSConditionSystem : ISystem
{
    private EntityQuery m_Query;

    /// <summary>
    /// Builds and caches the entity query used by this condition.
    /// </summary>
    /// <param name="state">The current ECS system state.</param>
    [BurstCompile]
    private void OnCreate(ref SystemState state)
    {
        m_Query = SystemAPI.QueryBuilder().WithAllRW<TransitionComponent>().WithAll<StateComponent, WithinDistanceECSConditionComponent, WithinDistanceECSConditionFlag, EvaluateFlag>().Build();
    }

    /// <summary>
    /// Schedules the condition job for matching entities.
    /// </summary>
    /// <param name="state">The current ECS system state.</param>
    [BurstCompile]
    private void OnUpdate(ref SystemState state)
    {
        state.Dependency = new WithinDistanceECSConditionJob().ScheduleParallel(m_Query, state.Dependency);
    }

    /// <summary>
    /// Job that evaluates the condition and updates transition validity counts.
    /// </summary>
    [BurstCompile]
    private partial struct WithinDistanceECSConditionJob : IJobEntity
    {
        /// <summary>
        /// Executes condition logic for a single entity's buffers.
        /// </summary>
        /// <param name="transitionComponents">Transition buffer.</param>
        /// <param name="stateComponents">State buffer.</param>
        /// <param name="conditionComponents">Condition runtime data buffer.</param>
        [BurstCompile]
        public void Execute(ref DynamicBuffer<TransitionComponent> transitionComponents, in DynamicBuffer<StateComponent> stateComponents, in DynamicBuffer<WithinDistanceECSConditionComponent> conditionComponents)
        {
            for (int i = 0; i < conditionComponents.Length; ++i) {
                var condition = conditionComponents[i];
                if (condition.TransitionIndex >= transitionComponents.Length) {
                    continue;
                }

                var transition = transitionComponents[condition.TransitionIndex];
                if (transition.SourceIndex >= stateComponents.Length) {
                    continue;
                }

                var sourceState = stateComponents[transition.SourceIndex];
                if (sourceState.Status == StateStatus.Inactive) {
                    continue;
                }

                var shouldEvaluate = transition.EvaluationMode switch
                {
                    EvaluationMode.Continuous => true,
                    EvaluationMode.OnStateFinished => sourceState.Status == StateStatus.Finished,
                    EvaluationMode.OnIterationComplete => sourceState.IterationComplete,
                    _ => true
                };

                if (!shouldEvaluate) {
                    continue;
                }

                if (math.distance(condition.Origin, condition.Target) <= condition.Distance) {
                    transition.ValidConditionCount++;
                    transitionComponents[condition.TransitionIndex] = transition;
                }
            }
        }
    }
}
```

This system checks each Condition entry, skips inactive or untimed evaluations, and increments `ValidConditionCount` when the distance check passes. It does not transition directly; transition triggering happens later in `TransitionEvaluationSystem`.

## How it runs

State Designer creates a `WithinDistanceECSConditionComponent` for the configured Condition. Its `TransitionIndex` connects the runtime values to the correct transition, and `WithinDistanceECSConditionFlag` controls when the system processes the entity.

The job checks the source state's status and follows the transition's Evaluation Mode. When the configured points are within **Distance**, it increments `ValidConditionCount`. `TransitionEvaluationSystem` then applies the transition's **All** or **Any** Condition Mode and changes state when its requirements pass. Cleanup systems reset the count for the next evaluation cycle.

## Verify the Condition

After the scripts compile, confirm that:

- **Within Distance ECS Condition** is available on a transition under **Documentation/ECS**.
- Selecting the transition shows Origin, Target, and Distance in the Element Inspector.
- In Play Mode, values within the configured distance allow the transition when its Evaluation Mode permits evaluation.
- Values outside the configured distance leave the Condition invalid.

If the Condition appears but does not evaluate, confirm that the entity has the required State Designer buffers and flags and that the system query includes `TransitionComponent`, `StateComponent`, `WithinDistanceECSConditionComponent`, `WithinDistanceECSConditionFlag`, and `EvaluateFlag`.

## Related pages

- [Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/)
- [States](https://opsive.com/support/documentation/state-designer/concepts/states/)
- [New Nodes](https://opsive.com/support/documentation/state-designer/new-nodes/)
- [GameObject Condition](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-condition/)
- [Entity Action](https://opsive.com/support/documentation/state-designer/new-nodes/entity-action/)
- [Entity Baking](https://opsive.com/support/documentation/state-designer/entity-baking/)

---

<a id="page-state-designer-variables"></a>

# Variables

[View this page online](https://opsive.com/support/documentation/state-designer/variables/)

Variables store values that a state machine needs to remember or share, such as a target, health value, cooldown, or selected menu item. Assigning the same Shared Variable to several compatible fields lets those States, Actions, and Conditions use one value instead of separate copies.

## Create and assign a Shared Variable

1. Open the **Shared Variables** panel in the State Designer editor.
2. Select **Graph**, **GameObject**, **Scene**, or **Project** according to who needs the value.
3. Select **Add Variable**, choose its value type, and enter a unique name.
4. Select a State, Action, or Condition that exposes a compatible Shared Variable field.
5. Select the circle beside the field and choose the variable.

Use **Add Group** to organize related rows. Drag variables and groups to reorder them. A group changes only the editor organization; it is not an additional runtime scope.

## Add a custom Shared Variable type

The Shared Variables panel can use a project-specific serializable value type or an explicit class derived from `SharedVariable<T>`. Add either custom type to **Tools > Opsive > Unit Options** after it compiles so it appears in the **Add Variable** type list.

C# rectangular arrays such as `int[,]` and jagged arrays such as `int[][]` are different types. The State Designer editor does not automatically present either one as a two-dimensional grid. Use a flat serializable value when the existing array control should edit the values, or use a derived Shared Variable when the project needs a named, specialized variable type that will be populated from code or drawn by a custom Control Type.

### Wrap a grid in a serializable value

Store the cells in a one-dimensional array and translate each row and column into a flat index. State Designer can draw the integer and array fields with its existing controls:

```csharp
using System;
using Opsive.GraphDesigner.Runtime.Variables;
using UnityEngine;

[Serializable]
public class IntGrid
{
    [Min(1)]
    [SerializeField] private int m_Columns = 1;
    [SerializeField] private int[] m_Values = Array.Empty<int>();

    public int Columns => m_Columns;
    public int Rows => m_Columns > 0 ? m_Values.Length / m_Columns : 0;

    public int this[int row, int column]
    {
        get => m_Values[(row * m_Columns) + column];
        set => m_Values[(row * m_Columns) + column] = value;
    }
}

public class UseIntGrid : Opsive.StateDesigner.Runtime.Actions.Action
{
    [SerializeField] protected SharedVariable<IntGrid> m_Grid;
}
```

Add `IntGrid` to Unit Options, then create an **Int Grid** Shared Variable. Keep the Values array length equal to the intended row count multiplied by Columns. Actions and Conditions can declare `SharedVariable<IntGrid>` fields and read a cell with `m_Grid.Value[row, column]`.

### Derive a named Shared Variable

An explicit Shared Variable class is useful when the variable itself should have a project-specific name or behavior. This valid declaration stores a jagged integer array:

```csharp
using Opsive.GraphDesigner.Runtime.Variables;

[System.Serializable]
public class IntGridVariable : SharedVariable<int[][]>
{
    public static implicit operator IntGridVariable(int[][] value)
    {
        return new IntGridVariable { Value = value };
    }
}
```

Add `IntGridVariable` to Unit Options, create an **Int Grid Variable**, and declare `IntGridVariable` fields on the Actions or Conditions that use it. The inherited `Value` property contains the `int[][]` value:

```csharp
m_Grid.Value = new[] {
    new[] { 1, 2 },
    new[] { 3, 4 }
};

int cell = m_Grid.Value[row][column];
```

Because each row in a jagged array can have a different length, validate the row and column before indexing data supplied at runtime. The derived class makes the type available to the Shared Variable system; it does not add a nested-array editor. Prefer the flat `IntGrid` wrapper for the built-in UI, or create a [Control Type](https://opsive.com/support/documentation/state-designer/extending-the-editor/control-types/) when authors need a purpose-built grid.

## Manage a variable from its row menu

Right-click a variable row in the Shared Variables panel to open its complete management menu.

| Command | When to use it |
| --- | --- |
| **Enable Property Binding / Disable Property Binding** | Connect the variable to a compatible C# property, or remove that connection. A bound variable cannot be moved to Project scope. |
| **Change Type** | Change the value type. Reassign State, Action, and Condition fields that are no longer compatible with the new type. |
| **Move To > Graph / GameObject / Scene / Project** | Move the value to another scope. State Designer updates graph references, removes the row from its current group, and blocks a move that would create a destination name/type conflict. |
| **Internal** | Keep a Graph variable available to nodes in this graph while hiding it from the State Machine component's configurable variables and from Subgraph override lists. Runtime override lookup also ignores it. Select **Internal** again to make the variable externally configurable. |
| **Rename** | Rename the variable and update its references in this graph. |
| **Duplicate** | Create an independent copy that can be renamed or given a different value. |
| **Delete** | Remove the variable. Resolve any fields that referred to the deleted row. |

**Internal** appears only on the **Graph** tab. It is useful for temporary counters, cached targets, and other implementation details that a State Machine component or parent Subgraph Reference should not override. It is not a security boundary and does not prevent nodes in the graph from reading or writing the value.

Right-click a group for **Rename**, **Duplicate**, or **Delete**. **Duplicate** creates a new empty group with a unique name; it does not duplicate the member variables. **Delete** removes only the group, and its variables remain available as ungrouped rows.

## Choose the correct scope

Where a variable is stored determines which state machines can use it:

| Scope | Typical use |
| --- | --- |
| **Graph** | One state machine owns the value. This is the normal starting point and the only scope that supports **Internal**. |
| **GameObject** | Several state machines on the same GameObject need the value. |
| **Scene** | State machines on different GameObjects in the current scene share the value. |
| **Project** | State machines in different scenes use a project-wide value. Project variables cannot bind to a scene component property. |
| **Dynamic** | A small number of fields in one running graph share a temporary name without creating a row in the panel. |

See [Scope](https://opsive.com/support/documentation/state-designer/variables/scope/) for storage components, Dynamic-variable rules, and a Play Mode test.

## Verify the value flow

Enter Play Mode with a variable visible in the panel. Run the State or Action that writes the value, then select another node assigned to the same variable. Confirm that both show the same runtime value.

For an Internal variable, also inspect the State Machine component or a parent Subgraph Reference. The variable should remain usable inside the graph but should not appear as an external override.

## Choose what you need next

- [Accessing Variables](https://opsive.com/support/documentation/state-designer/variables/accessing-variables/) explains how a State, Action, or another script reads and updates a Shared Variable.
- [Scope](https://opsive.com/support/documentation/state-designer/variables/scope/) covers Graph, GameObject, Scene, Project, and Dynamic values.
- [Property Binding](https://opsive.com/support/documentation/state-designer/variables/property-binding/) connects a Shared Variable to a C# property so the state machine and component use the same value.
- [Entity Variables](https://opsive.com/support/documentation/state-designer/variables/entity/) registers, reads, and updates Shared Variables from Entity Actions and Conditions.
- [Overview](https://opsive.com/support/documentation/state-designer/overview/) covers graph navigation, panels, preferences, and shortcuts; the State, Action, and Condition pages cover their own row and Inspector commands.

---

<a id="page-state-designer-variables-accessing-variables"></a>

# Accessing Variables

[View this page online](https://opsive.com/support/documentation/state-designer/variables/accessing-variables/)

Access a Shared Variable when an Action or another component needs to read or update a value used by the state machine. Assigning the same variable to multiple Action fields lets them work with one value, while the `StateMachine` API lets your own scripts initialize or inspect that value.

## Assign a Shared Variable to an Action

1. Create a Shared Variable in the Shared Variables pane. For this example, create a GameObject variable named **Target**.
2. Add a `SharedVariable<GameObject>` field to the custom Action.
3. Select the Action in the graph and assign **Target** to that field in the Inspector.
4. Read or update the assigned variable through its `Value` property.

This Action excerpt reads the current target and assigns the Player GameObject when the value is empty:

```csharp
using Opsive.GraphDesigner.Runtime.Variables;
using Opsive.StateDesigner.Runtime.Actions;
using Opsive.StateDesigner.Runtime.States;
using UnityEngine;

public class FindTarget : Action
{
    [Tooltip("The object that the agent is searching for.")]
    [SerializeField] protected SharedVariable<GameObject> m_Target;

    public override StateStatus OnUpdate()
    {
        GameObject targetGameObject = m_Target.Value;
        if (targetGameObject == null) {
            m_Target.Value = GameObject.Find("Player");
        }
```

Assign **Target** to each compatible field that should share this value. Those fields then refer to the same Shared Variable instead of keeping separate GameObject values.

## Access a Graph variable from a component

Get a reference to the `StateMachine` component, look up the variable by its name and type, and use the returned `SharedVariable.Value` property:

```csharp
using Opsive.GraphDesigner.Runtime.Variables;
using Opsive.StateDesigner.Runtime;
using UnityEngine;

public class AccessVariable : MonoBehaviour
{
    public StateMachine m_StateMachine;

    public void Start()
    {
        SharedVariable<GameObject> target = m_StateMachine.GetVariable<GameObject>("Target");
        target.Value = gameObject;
    }
}
```

This example gets the Graph-scope GameObject variable named **Target** and assigns the component's GameObject to it.

## Access a variable in another scope

`GetVariable` uses Graph scope when no scope is supplied. Add the `SharingScope` parameter when the variable belongs to another [scope](https://opsive.com/support/documentation/state-designer/variables/scope/):

```csharp
SharedVariable target = m_StateMachine.GetVariable("Target", SharedVariable.SharingScope.Scene);
```

You can also access the component or asset that owns a GameObject-, Scene-, or Project-scope variable and call its typed `GetVariable` method directly:

```csharp
using Opsive.GraphDesigner.Runtime.Variables;
using Opsive.GraphDesigner.Runtime;
using UnityEngine;

public class AccessVariable : MonoBehaviour
{
    public StateMachine m_StateMachine;
    public GameObjectSharedVariables m_GameObjectSharedVariables;
    public SceneSharedVariables m_SceneSharedVariables;

    public void Start()
    {
        var target = m_StateMachine.GetVariable<GameObject>("Target"); // Graph Scope.
        target = m_GameObjectSharedVariables.GetVariable<GameObject>("Target"); // GameObject Scope.
        target = m_SceneSharedVariables.GetVariable<GameObject>("Target"); // Scene Scope.
        target = ProjectSharedVariables.Instance.GetVariable<GameObject>("Target"); // Project Scope.
    }
}
```

## How it runs

An Action field assigned in the Inspector holds a reference to the selected Shared Variable. Reading or writing `Value` therefore reads or updates the value used by every other compatible field assigned to that same variable.

At runtime, `StateMachine.GetVariable<T>("Target")` searches Graph scope. The overload with `SharedVariable.SharingScope` searches the requested scope instead. A lookup returns `null` when the name, type, and scope do not identify a matching variable, so confirm the result before using `Value` in code that may run with different graph setups.

## Important choices

- Match the variable name used in code with the name shown in the Shared Variables pane.
- Use the same value type in the Shared Variable, Action field, and generic `GetVariable<T>` call.
- Keep a value in Graph scope when only one graph needs it. Choose GameObject, Scene, or Project scope only when that wider set of state machines must share it.
- Use the scoped `StateMachine.GetVariable` overload when the state machine should select the scope. Use a `GameObjectSharedVariables`, `SceneSharedVariables`, or `ProjectSharedVariables` reference when your script already has the owning container.

## Verify in Play Mode

Enter Play Mode with **Target** visible in the Shared Variables pane. Run the Action or component that assigns the Player or current GameObject, then confirm that **Target** changes to that object. Select another state that uses the same variable and confirm that its assigned field shows the same runtime value.

If the value does not change, verify the variable name, value type, selected scope, and Inspector assignment. A code lookup that does not match those details returns `null`.

## Related pages

- [Variables](https://opsive.com/support/documentation/state-designer/variables/) introduces Shared Variables and their supporting workflows.
- [Blackboard](https://opsive.com/support/documentation/state-designer/concepts/blackboard/) shows how to create and assign Shared Variables in the editor.
- [Scope](https://opsive.com/support/documentation/state-designer/variables/scope/) explains Graph, GameObject, Scene, Project, and Dynamic variables.
- [Property Binding](https://opsive.com/support/documentation/state-designer/variables/property-binding/) connects a Shared Variable to a component property.
- [Creating a GameObject Action](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-action/) shows Shared Variable fields in a custom Action.

---

<a id="page-state-designer-variables-scope"></a>

# Scope

[View this page online](https://opsive.com/support/documentation/state-designer/variables/scope/)

Choose a variable scope according to who needs the value. Keep a value in the graph when it belongs to one state machine, or use a broader scope when multiple state machines must read and change the same value.

## Choose a scope in the editor

The Shared Variables pane has four tabs for variables that are created ahead of time: **Graph**, **GameObject**, **Scene**, and **Project**. Select the tab before adding or editing a variable.

![The Shared Variables scope tabs: Graph, GameObject, Scene and Project.](https://opsive.com/wp-content/uploads/2024/11/VariableScopeTabs.webp?v=cd55b08b7209)

Dynamic variables are selected from an individual Shared Variable field instead of from a tab.

## Which scope should you use?

| Scope | Use it when | Available to | Storage |
| --- | --- | --- | --- |
| **Graph** | The value belongs to one graph. This is the usual starting point. | Nodes in the attached graph. | The graph's Shared Variables. |
| **GameObject** | Multiple state machines on the same GameObject need one value. | State machines attached to that GameObject. | A `GameObjectSharedVariables` component on the GameObject. |
| **Scene** | State machines on different GameObjects in one scene need one value. | State machines in the running scene. | A `SceneSharedVariables` component in the scene. |
| **Project** | State machines in different scenes need a project-wide value. | State machines throughout the project. | The `ProjectSharedVariables` ScriptableObject in a `Resources` folder. |
| **Dynamic** | A small number of fields in one running graph need a temporary shared value without adding it to the Shared Variables pane. | Fields in the attached graph that use the same Dynamic name. | Created for the graph at runtime. |

By default, State Designer creates the Project asset at `Assets/Opsive/GraphDesigner/Resources/ProjectSharedVariables.asset`. You can move it, but it must remain inside a `Resources` folder so it can be loaded at runtime.

## Create a Dynamic variable

In the Element Inspector, select the circle beside a compatible Shared Variable field and choose **(Dynamic)**.

![A Shared Variable field menu showing the (Dynamic) option.](https://opsive.com/wp-content/uploads/2024/11/DynamicVariableSelection.png)

Enter the shared name in the **Name** field that appears.

![A Dynamic Shared Variable field showing its Name text box.](https://opsive.com/wp-content/uploads/2024/11/DynamicVariableName.png)

Use the exact same name and variable type in every field that should share the Dynamic value. Names are case-sensitive, and a Dynamic name must not match an existing Graph variable name.

## How it runs

A Graph variable is resolved from the attached graph. A GameObject variable is resolved from the `GameObjectSharedVariables` component on the state machine's GameObject. Scene and Project variables are resolved from their respective shared containers.

Dynamic fields with the same case-sensitive name and type are mapped to the same runtime variable within the attached graph. They do not appear as a fifth tab because they are created from the fields that use them.

## Verify the scope

Reference the same variable from two compatible fields, enter Play Mode, and change the value through one of them. Confirm that the other field reads the same value.

For a broader scope, repeat the check from two state machines on the intended GameObject or in the intended scene. For a Dynamic variable, confirm that both fields use the same spelling and type. State Designer reports an error if Dynamic variables with the same name use different types or if a Dynamic name conflicts with a Graph variable.

## Related pages

- [Variables](https://opsive.com/support/documentation/state-designer/variables/)
- [Accessing Variables](https://opsive.com/support/documentation/state-designer/variables/accessing-variables/)
- [Property Binding](https://opsive.com/support/documentation/state-designer/variables/property-binding/)
- [Entity Variables](https://opsive.com/support/documentation/state-designer/variables/entity/)
- [Save and Load](https://opsive.com/support/documentation/state-designer/save-load/)

---

<a id="page-state-designer-variables-property-binding"></a>

# Property Binding

[View this page online](https://opsive.com/support/documentation/state-designer/variables/property-binding/)

Use a property binding when a State Designer Shared Variable and a property on one of your components should represent the same value. This lets States and Actions work with a value such as health while other gameplay code continues to use the component property.

The PropertyBinding sample scene contains a working example.

## Prepare the property

The component must expose a C# property with both a getter and a setter. This example exposes the current health amount:

```csharp
public class Health : MonoBehaviour
{
    [Tooltip("The starting health value")]
    [SerializeField] protected float m_StartHealth = 100;

    private float m_HealthAmount;

    public float HealthAmount { get => m_HealthAmount; set => m_HealthAmount = value; }
}
```

## Bind the Shared Variable

1. Create a Shared Variable with the same value type as the property.
2. Right-click its row in the Shared Variables pane and select **Enable Property Binding**.
3. In **Object**, select the GameObject or component that owns the property.
4. In **Binding**, select the compatible property.

![Property Binding controls with Agent selected as the Object and Health selected as the Binding.](https://opsive.com/wp-content/uploads/2024/11/HealthPropertyBinding-1024x85.png)

## How it runs

The binding connects SharedVariable.Value directly to the selected property. Reading the Shared Variable calls the property getter. Writing the Shared Variable calls the property setter. Code inside and outside the State Machine therefore uses the same underlying value.

## Choose the source and value flow

- **Object:** Select the GameObject or component that contains the property. When a GameObject is selected, State Designer finds the component that declares the chosen property.
- **Binding:** Select a public instance property whose value type matches the Shared Variable.
- **Value flow:** Property binding is two-way. Reads use the getter and writes use the setter; there is no separate direction setting.

## Verify the binding

1. Enter Play Mode with a known value on the bound component property.
2. Read the Shared Variable and confirm that it returns the property value.
3. Change the Shared Variable from a State or Action and confirm that the component property changes.
4. Change the property through another script and confirm that the next Shared Variable read returns the updated value.

## Supported caveats

- The property must provide both a getter and a setter.
- Property binding does not work with fields.
- The property type must match the Shared Variable type.
- Property bindings are supported on non-project-level variables; Project variables cannot reference a component property.

## Related pages

- [Variables](https://opsive.com/support/documentation/state-designer/variables/)
- [Accessing Variables](https://opsive.com/support/documentation/state-designer/variables/accessing-variables/)
- [Variable Scope](https://opsive.com/support/documentation/state-designer/variables/scope/)
- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)
- [GameObject Action](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-action/)

---

<a id="page-state-designer-variables-entity"></a>

# Entity Variables

[View this page online](https://opsive.com/support/documentation/state-designer/variables/entity/)

Entity Variables allow ECS Actions and Conditions to share values through an entity's `SharedVariableElement` buffer. Use this pattern when ECS state logic needs to read or update a Shared Variable, such as storing the Entity selected as a target.

The value type must be unmanaged and no larger than 16 bytes. The example below uses `SharedVariable<Entity>`.

## Authoring setup

Declare the Shared Variable and a typed `ECSSharedVariableIndex<Entity>` in the ECS Action. Register the Shared Variable in `AddBufferElement`, then retain the returned index for the runtime component:

```csharp
[Tooltip("The entity that should be targeted.")]
[SerializeField] SharedVariable<Entity> m_TargetEntity;

private ECSSharedVariableIndex<Entity> m_TargetEntityIndex;

/// <summary>
/// Registers the target SharedVariable and adds the buffer element to the entity.
/// </summary>
/// <param name="world">The world that the entity exists in.</param>
/// <param name="entity">The entity that the IBufferElementData should be assigned to.</param>
/// <param name="registry">The ECS variable registry for registering SharedVariable fields.</param>
/// <param name="gameObject">The GameObject that the entity is attached to.</param>
/// <param name="stateMachineID">The ID of the state machine running the state.</param>
/// <param name="index">The runtime index of the state.</param>
/// <returns>The index of the element within the buffer.</returns>
public override int AddBufferElement(World world, Entity entity, ECSVariableRegistry registry, GameObject gameObject, int stateMachineID, ushort index)
{
    m_TargetEntityIndex = new ECSSharedVariableIndex<Entity>(registry.Register(m_TargetEntity));
    return base.AddBufferElement(world, entity, registry, gameObject, stateMachineID, index);
}
```

Store the integer buffer index in the Action's runtime component so its ECS system can locate the value for each entity:

```csharp
public override FindTargetComponent GetBufferElement()
{
    return new FindTargetComponent {
        Index = RuntimeIndex,
        TargetEntityVariableIndex = m_TargetEntityIndex.Index,
    };
}

/// <summary>
/// The DOTS data structure for the FindTarget struct.
/// </summary>
public struct FindTargetComponent : IBufferElementData
{
    [Tooltip("The index of the node.")]
    public ushort Index;
    [Tooltip("Buffer index into SharedVariableElement for the target entity.")]
    public int TargetEntityVariableIndex;
}
```

## How it runs

During State Machine initialization, `ECSVariableRegistry.Register` assigns the Shared Variable a stable buffer index. The registry then bakes its initial value into the entity's `SharedVariableElement` buffer.

The ECS system includes `DynamicBuffer<SharedVariableElement>` in its query. It can read the value with `Get<T>(index)` and write it with `Set(index, value)`:

```csharp
foreach (var (stateComponents, findTargetComponents, sharedVariables) in
         SystemAPI.Query<DynamicBuffer<StateComponent>, DynamicBuffer<FindTargetComponent>, DynamicBuffer<SharedVariableElement>>()
             .WithAll<FindTargetFlag, EvaluateFlag>()) {
    for (int i = 0; i < findTargetComponents.Length; ++i) {
        var findTargetComponent = findTargetComponents[i];
        var targetEntity = sharedVariables.Get<Entity>(findTargetComponent.TargetEntityVariableIndex);

        // Find or update the target Entity here.

        sharedVariables.Set(findTargetComponent.TargetEntityVariableIndex, targetEntity);
    }
}
```

Other ECS Actions or Conditions that reference the same Shared Variable can use its registered buffer value without storing a managed object in their runtime component.

## Key choices

- **Value type:** Use only unmanaged values that fit within the 16-byte `SharedVariableElement` limit.
- **Scope:** Shared Variable names and scopes still determine which value is shared. Use Graph scope for one State Machine graph, or choose a broader scope only when other graphs need the same value.
- **Runtime storage:** Store the registered integer index in the ECS component. Read and write the value through `DynamicBuffer<SharedVariableElement>` rather than placing the managed Shared Variable in ECS data.
- **Access:** Use `Get<T>(index)` when the system only needs the current value and `Set(index, value)` when it changes that value for other state logic.

## Verify the result

Run the State Machine and confirm that:

- Registration returns a valid buffer index for the Shared Variable.
- The ECS system can read the initial value from `SharedVariableElement`.
- A value written with `Set` is returned by the next `Get` using the same index.

If registration fails, confirm that the Shared Variable is assigned and its value type is unmanaged and no larger than 16 bytes. If the system cannot access the value, confirm that its query includes `DynamicBuffer<SharedVariableElement>` and the expected Action or Condition flags.

## Related pages

- [Variable Scope](https://opsive.com/support/documentation/state-designer/variables/scope/)
- [Accessing Variables](https://opsive.com/support/documentation/state-designer/variables/accessing-variables/)
- [Entity Action](https://opsive.com/support/documentation/state-designer/new-nodes/entity-action/)
- [Entity Condition](https://opsive.com/support/documentation/state-designer/new-nodes/entity-condition/)
- [Entity Baking](https://opsive.com/support/documentation/state-designer/entity-baking/)

---

<a id="page-state-designer-entity-baking"></a>

# Entity Baking

[View this page online](https://opsive.com/support/documentation/state-designer/entity-baking/)

[Entity Baking](https://docs.unity3d.com/Packages/com.unity.entities@1.0/manual/baking.html) converts authored State Machine data into runtime ECS data. Use it when an Entity workflow needs to create agents from the same State Machine prefab, such as spawning 100 instances from one baked configuration.

## Prerequisites

- Meet the [State Designer requirements](https://opsive.com/support/documentation/state-designer/requirements/).
- Add and enable the State Machine component on the prefab.
- Configure the State Machine to start when enabled so its data is baked automatically.
- Have the State Machine prefab ready to assign to the spawner.

The Entity sample scene includes an EntitySpawner component with a working example.

## Set up the baked prefab

1. Create an EntitySpawner authoring component with a field for the State Machine prefab.
2. Add a Baker that converts the assigned prefab to an entity prefab and stores it in SpawnData.
3. Add the EntitySpawner component to an authoring GameObject and assign the State Machine prefab.

The authoring component and its Baker can be defined as follows:

```csharp
public struct SpawnData : IComponentData
{
    [Tooltip("The entity prefab that should be spawned.")]
    public Entity Prefab;
}

public class EntitySpawner : MonoBehaviour
{
    [Tooltip("A reference to the state machine prefab.")]
    [SerializeField] protected GameObject m_SpawnPrefab;

    /// <summary>
    /// Bakes the spawn data.
    /// </summary>
    private class Baker : Baker<EntitySpawner>
    {
        /// <summary>
        /// Bakes the data.
        /// </summary>
        /// <param name="authoring">The parent authoring component.</param>
        public override void Bake(EntitySpawner authoring)
        {
            if (authoring.m_SpawnPrefab == null) {
                return;
            }
            var entity = GetEntity(TransformUsageFlags.Dynamic);
            var entityPrefab = GetEntity(authoring.m_SpawnPrefab, TransformUsageFlags.Dynamic);
            AddComponentObject(entity, new SpawnData
            {
                Prefab = entityPrefab,
            });
        }
    }
}
```

## Spawn the entities

Create a system that waits for SpawnData, runs once, and instantiates the baked State Machine prefab:

```csharp
public partial struct EntitySpawnerSystem : ISystem
{
    /// <summary>
    /// Sets the system requirements.
    /// </summary>
    /// <param name="state">The current SystemState.</param>
    private void OnCreate(ref SystemState state)
    {
        state.RequireForUpdate<SpawnData>();
    }

    /// <summary>
    /// Spawns the entities.
    /// </summary>
    /// <param name="state">The current SystemState.</param>
    private void OnUpdate(ref SystemState state)
    {
        state.Enabled = false;

        var spawner = SystemAPI.ManagedAPI.GetSingleton<SpawnData>();
        var entities = state.EntityManager.Instantiate(spawner.Prefab, 100, Allocator.Temp);

        // Any custom setup for each entity. This can include adding new components, enabling components, setting entity data, etc.
    }
}
```

## How it runs

During baking, the EntitySpawner Baker stops if no prefab is assigned. Otherwise, it converts the assigned State Machine prefab to an entity prefab and stores that reference in SpawnData.

The EntitySpawnerSystem waits until SpawnData exists. On its first update, it disables itself and instantiates 100 entities from the baked prefab. The returned entity collection can then be used for per-agent setup such as adding components, enabling components, or setting entity data.

## Verify the result

Run the scene containing the configured EntitySpawner and verify that:

- 100 entity instances are created from the assigned State Machine prefab.
- The spawn happens once rather than on every system update.
- Each created entity can receive any additional setup required by the project.

If no entities are created, first confirm that a prefab is assigned. If the State Machine data is not available at runtime, confirm that the State Machine component is enabled and configured to start when enabled.

## Related pages

- [Requirements](https://opsive.com/support/documentation/state-designer/requirements/)
- [Entity Action](https://opsive.com/support/documentation/state-designer/new-nodes/entity-action/)
- [Entity Condition](https://opsive.com/support/documentation/state-designer/new-nodes/entity-condition/)

---

<a id="page-state-designer-events"></a>

# Events

[View this page online](https://opsive.com/support/documentation/state-designer/events/)

Use an event when something outside the current state should notify a state machine that an action occurred. A **Send Event** Action publishes a named event, and a **Has Received Event** Condition can use that event to allow a transition without creating a direct reference between the sender and the receiving state.

Events can be sent by an Action in a graph or by your own code. They can target one GameObject or be global, and they can carry up to three optional values.

## Set up an event in the editor

1. Add a **Send Event** Action to the state that should publish the event.
2. Enter a nonempty **Event Name**.
3. Choose targeted or global delivery. For a targeted event, select the receiving GameObject.
4. Assign up to three optional argument values when the receiver needs data from the sender.

![The Send Event Action Inspector with the event name, global-event choice, target GameObject, and optional arguments.](https://opsive.com/wp-content/uploads/2026/03/SendEvent.png?v=f6b9e32e877d)

5. Select the transition that should react to the event and add a **Has Received Event** Condition.
6. Use the same Event Name and global-event choice as the sender.
7. Assign optional stored-value Shared Variables when the transition or destination state needs the sent arguments.
8. Use **Continuous** evaluation when the transition should respond as soon as the event arrives.

![The Has Received Event Condition Inspector with the matching event name, delivery choice, target, and stored values.](https://opsive.com/wp-content/uploads/2026/02/HasReceivedEventCondition.png?v=89fe0673970c)

## Example: pass a value to a responding state

Suppose a state machine is in a Waiting state. A graph Action or script sends `MyEvent` with the integer value `5` to that state machine's GameObject. The Waiting-to-Respond transition uses **Has Received Event** with the same name and stores the first argument in a Shared Variable.

When `MyEvent` arrives, the transition becomes valid, the state machine enters Respond, and the stored value is `5`. This keeps the notification separate from the behavior that Respond performs.

## How it runs

The receiving Condition registers for its configured event when the state machine starts. When a matching event arrives, it records the optional argument values and reports valid when the transition checks it.

**Has Received Event** is one-shot: after it reports valid, it clears the received flag. A later transition therefore requires the event to be sent again.

## Important choices

- Use a **targeted event** when one known GameObject should receive the notification. The sender and receiver must refer to the same target.
- Use a **global event** when the notification is not tied to one GameObject. Both the sender and receiver must enable the global option.
- Keep the Event Name nonempty and identical on both sides. An empty name logs an error and cannot produce a useful event.
- Match the number and types of sent arguments with the receiver's stored-value fields.
- Use Shared Variables for stored arguments when later Actions or Conditions need those values.

## Verify in Play Mode

Trigger the sender while the receiving state machine is in Waiting. Confirm that the editor highlights Respond after the event arrives. If the event carries an argument, inspect the assigned Shared Variable and confirm that it contains the sent value.

If the transition does not run, first compare the Event Name, targeted/global choice, target GameObject, and argument setup on both sides.

## Send an event from code

Use `EventHandler.ExecuteEvent` to send the same targeted event from a script:

```csharp
using Opsive.Shared.Events;
using Opsive.StateDesigner.Runtime;

var stateMachine = GetComponent<StateMachine>();
EventHandler.ExecuteEvent<int>(stateMachine.gameObject, "MyEvent", 5);
```

This sends `MyEvent` to the state machine's GameObject with one integer argument whose value is `5`. A global event omits the target object and requires the receiving Condition to use the global option.

## Receive an event from code

Code outside the graph can subscribe to the same targeted event:

```csharp
using Opsive.Shared.Events;
using Opsive.StateDesigner.Runtime;
using UnityEngine;

public class EventListenerExample : MonoBehaviour
{
    private StateMachine m_StateMachine;

    private void OnEnable()
    {
        m_StateMachine = GetComponent<StateMachine>();
        EventHandler.RegisterEvent<int>(m_StateMachine.gameObject, "MyEvent", ReceivedEvent);
    }

    private void ReceivedEvent(int arg1)
    {
        Debug.Log($"Received MyEvent with arg: {arg1}");
    }

    private void OnDisable()
    {
        EventHandler.UnregisterEvent<int>(m_StateMachine.gameObject, "MyEvent", ReceivedEvent);
    }
}
```

Register and unregister with the same target, event name, and argument signature.

## Related pages

- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/) explains how graph Actions perform work.
- [Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/) explains how Conditions allow transitions.
- [States](https://opsive.com/support/documentation/state-designer/concepts/states/) explains how the destination state runs its behavior.
- [Variables](https://opsive.com/support/documentation/state-designer/variables/) introduces Shared Variables used to store event arguments.
- [Accessing Variables](https://opsive.com/support/documentation/state-designer/variables/accessing-variables/) shows how scripts read and update Shared Variables.

---

<a id="page-state-designer-subgraphs"></a>

# Subgraphs

[View this page online](https://opsive.com/support/documentation/state-designer/subgraphs/)

<iframe width="100%" height="600" src="https://www.youtube.com/embed/Q3IRpcxKMvE?rel=0&amp;showinfo=0" title="State Designer Subgraphs video" loading="lazy" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>

If the embedded player is unavailable, [watch the Subgraphs video on YouTube](https://www.youtube.com/watch?v=Q3IRpcxKMvE).

Subgraphs store State Designer behavior in reusable ScriptableObject assets. Split behavior into a Subgraph when the same group of States, Actions, and transitions appears in several graphs, when a large graph needs a clearer high-level structure, or when the referenced behavior must be swapped.

## Choose how to create the Subgraph

State Designer exposes two different editor workflows:

| Workflow | Result |
| --- | --- |
| **Export** in the operations toolbar | Copies the entire current graph into a new Subgraph asset. The source graph remains unchanged. Use this when the whole graph should become reusable. |
| Right-click a State selection and choose **Save as Subgraph** | Extracts a valid region into a new Subgraph asset and replaces that region with a Subgraph Reference. Entry and exit transitions are reconnected to the reference. Use this while refactoring part of an existing state machine. |

### Save selected States as a Subgraph

1. Select every State in the region that should become reusable.
2. Right-click the selection and choose **Save as Subgraph**.
3. Choose the asset path and name.
4. Inspect the new Subgraph Reference, its incoming and outgoing transitions, and its Shared Variable Overrides.

The command becomes available only when the selection can be represented by one reference:

- Exactly one transition or event enters the selected region from outside it.
- Every selected State is reachable from that entry.
- No more than one selected exit State transitions to an unselected State.
- That exit State cannot also transition back into the selected region.

State Designer saves the selected region, replaces it with a Subgraph Reference, and preserves the valid external transition path. Shared Variables that are externally configurable can be exposed as overrides on the reference. A Graph variable marked **Internal** remains usable inside the Subgraph but is intentionally omitted from those override controls. See [Variables](https://opsive.com/support/documentation/state-designer/variables/) for the **Internal** command.

If **Save as Subgraph** is disabled, simplify the selection to one entry and one optional exit, then check that every selected State is reachable from the entry.

**Checkpoint:** the parent graph enters one Subgraph Reference, the reference opens the expected selected States and transitions, and its outgoing transition returns to the same unselected State as before.

## Create and reference a Subgraph

Author the reusable States and transitions in a graph, then use **Export** in the State Designer toolbar to create a Subgraph asset. In the parent graph, add a Subgraph Reference state and assign one or more Subgraphs to its **Subgraphs** list.

![A Subgraph Reference state placed in a parent State Designer graph.](https://opsive.com/wp-content/uploads/2026/03/SubgraphReferenceState.png?v=5b0ead8e7cd2)

The Subgraph Reference state lets you assign one or more subgraphs that should be loaded when the graph initializes. By default, it uses every subgraph in the Subgraphs list.

Use Shared Variable Overrides on the reference when the parent graph should provide different values without changing the Subgraph asset.

## How it runs

When the graph initializes, State Designer replaces each Subgraph Reference with the nodes injected from its selected Subgraphs. The referenced States and Actions perform the behavior, and their transitions continue to control execution. When several Subgraphs are assigned to one reference, they are processed in list order.

If selection logic changes later, reevaluating the Subgraph References rebuilds the injected content and restarts the graph with the new selection.

## Key reference and reuse choices

### Runtime selection

If you want runtime selection logic, subclass SubgraphReference (or implement ISubgraphReferenceNode) and override EvaluateSubgraphs. That method runs before Subgraphs is read, so you can choose which subgraph(s) to return.

```csharp
using Opsive.GraphDesigner.Runtime;
using Opsive.StateDesigner.Runtime;
using Opsive.StateDesigner.Runtime.States;
using UnityEngine;

public class RandomSubgraphReference : SubgraphReference
{
    private Subgraph[] m_Selection;

    public override Subgraph[] Subgraphs => m_Selection != null ? m_Selection : m_Subgraphs;

    /// <summary>
    /// Performs runtime selection before subgraphs are injected.
    /// </summary>
    public override void EvaluateSubgraphs(IGraphComponent graphComponent)
    {
        if (m_Subgraphs == null || m_Subgraphs.Length == 0) {
            return;
        }

        m_Selection = new[] { m_Subgraphs[Random.Range(0, m_Subgraphs.Length)] };
    }
}
```

In this example, `EvaluateSubgraphs` picks one random Subgraph and stores it in `m_Selection`, then the `Subgraphs` property returns that selection.

### Variable overrides

Subgraph Reference supports `SharedVariableOverride[]`, so a parent graph can provide values to variables defined inside the Subgraph. Each override maps:

- **Source:** A variable defined in the Subgraph.
- **Override:** The value or variable the parent should use instead.

This keeps one reusable Subgraph asset while allowing each parent to supply values such as different targets, speeds, timers, or flags. If an override entry is empty, the Subgraph keeps its own value for that variable.

### Reevaluation

At runtime, Subgraph Reference nodes are replaced by injected subgraph nodes. If your selection logic changes later (for example, random/conditional selection), call:

```csharp
m_StateMachine.ReevaluateSubgraphReferences();
```

This reevaluates all Subgraph References, calls `EvaluateSubgraphs` again, rebuilds the injected nodes, and restarts the graph with the new Subgraph selection. You can also trigger this through the built-in `ReevaluateSubgraphReferences` Action.

### Pooling

If you frequently switch subgraphs at runtime, pooling can reduce overhead. The key pattern is:

1.  Instantiate subgraph instances ahead of time.
2.  Call Deserialize() on each instance.
3.  Set Pooled = true.
4.  Reuse those instances instead of creating new ones on demand.

```csharp
using Opsive.StateDesigner.Runtime;
using UnityEngine;

public class SubgraphPooler : MonoBehaviour
{
    [Tooltip("A reference to the state machine that receives pooled subgraphs.")]
    public StateMachine m_StateMachine;
    [Tooltip("The subgraph asset to clone into the pool.")]
    public Subgraph m_Subgraph;
    [Tooltip("Pool size.")]
    public int m_PoolSize = 5;

    private Subgraph[] m_SubgraphPool;
    private int m_Index;

    private void Awake()
    {
        m_SubgraphPool = new Subgraph[m_PoolSize];
        for (int i = 0; i < m_PoolSize; ++i) {
            m_SubgraphPool[i] = Instantiate(m_Subgraph);
            m_SubgraphPool[i].Deserialize();
            m_SubgraphPool[i].Pooled = true;
        }
    }

    public void Assign()
    {
        m_StateMachine.Subgraph = m_SubgraphPool[m_Index];
        m_Index = (m_Index + 1) % m_SubgraphPool.Length;
    }
}
```

If you are swapping Subgraphs through Subgraph Reference selection logic, return pooled Subgraphs from `EvaluateSubgraphs` and call `ReevaluateSubgraphReferences()` when you want the switch to happen.

## Verify the result

Enter Play mode and confirm that:

- The parent graph runs the States from the assigned Subgraph.
- Each Shared Variable Override supplies the expected value, while an empty override retains the Subgraph default.
- Changing runtime selection and reevaluating the references runs the newly selected Subgraph content.

## Related pages

- [Debugging](https://opsive.com/support/documentation/state-designer/debugging/)
- [Subgraph Reference](https://opsive.com/support/documentation/state-designer/concepts/states/subgraph-reference/)
- [States](https://opsive.com/support/documentation/state-designer/concepts/states/)
- [Variable Scope](https://opsive.com/support/documentation/state-designer/variables/scope/)
- [Accessing Variables](https://opsive.com/support/documentation/state-designer/variables/accessing-variables/)
- [API](https://opsive.com/support/documentation/state-designer/api/)
- [Overview](https://opsive.com/support/documentation/state-designer/overview/)

---

<a id="page-state-designer-debugging"></a>

# Debugging

[View this page online](https://opsive.com/support/documentation/state-designer/debugging/)

Use this guide when no State activates, the wrong transition wins, a State never finishes, or a Shared Variable has an unexpected value. Start with the Error Window, then diagnose active flow and data in Play Mode.

## Start with the Error Window

Open **Tools > Opsive > State Designer > Error Window**, select the status-bar error count, or press **Ctrl/Cmd+E**. Select an error to identify its State or transition.

Resolve structural problems before Play Mode:

1. Connect Start to the intended initial State.
2. Assign required Actions, Conditions, Subgraphs, and fields.
3. Confirm that every transition has a valid source and destination.
4. Resolve missing Shared Variables and object references.
5. Clear compiler errors that can remove node types or fields from the selectors.

A clean Error Window means the editor found no known structural or serialized-field problem. It does not prove that transition logic or runtime values are correct.

## Follow active flow

Enter Play Mode with the editor open. Identify the active State, then inspect the transition that should leave it.

![A State Designer graph highlights the active State during Play Mode.](https://opsive.com/wp-content/uploads/2026/03/PatrolChaseAttackFleeActive.png?v=16541327b199)

If the State is wrong, trace from Start and inspect the first unexpected transition. If the State is correct but never changes, inspect its completion status, Evaluation Mode, and live Conditions. Pause when the problem is visible.

## Inspect Actions, Conditions, and values

- In an Action State, identify the first Action that remains Running or fails to complete.
- On a transition, inspect Condition Mode, Evaluation Mode, disabled rows, and the live values used by each Condition.
- In Shared Variables, confirm the intended name, type, scope, Internal/read-only state, and property binding.
- For a Subgraph Reference, confirm the asset and every override mapping.

Use a field's watch control to display a supported live value on the State. Do not create duplicate variables to hide a scope or binding problem.

## Diagnose common symptoms

| Symptom | Check | Fix |
| --- | --- | --- |
| No State becomes active. | Owner selection, enabled State Machine, Start connection, active GameObject, and compiler errors. | Enable/select the correct owner, connect Start, and clear errors. |
| The wrong initial State runs. | Start connection and selected state machine. | Connect Start to the intended State and verify the operations-toolbar selection. |
| A State never finishes. | Action execution mode and the first Action still Running. | Correct the Action's completion rule or use a transition that evaluates continuously. |
| A transition never evaluates. | Evaluation Mode and State lifecycle. | Use Continuous, On State Finished, or On Iteration Complete according to the source State. |
| The wrong transition wins. | Competing valid Conditions and serialized transition order. | Follow [Transition Evaluation and Priority](https://opsive.com/support/documentation/state-designer/concepts/transition-evaluation-and-priority/). |
| The graph flickers or loops. | Always-true Conditions, Any, self-transition re-entry, and entry Actions that reverse the previous value. | Add a stable state change, cooldown, consumed event, or narrower interrupt. |
| A value differs from the Inspector. | Scope, Internal/read-only state, property binding, and scripts that write it. | Inspect the owning variable and binding instead of creating a replacement. |
| A Subgraph uses the wrong object. | Override names, types, source variables, and runtime replacement. | Correct the Subgraph Reference mapping and retest in isolation. |

## Reduce the graph safely

Duplicate the owner or use a test scene. Disable one transition at a time, replace a project Action with Log, and use fixed values instead of live variables. Restore one dependency at a time after the smallest graph reproduces the issue.

## Related pages

- [Overview](https://opsive.com/support/documentation/state-designer/overview/)
- [States](https://opsive.com/support/documentation/state-designer/concepts/states/)
- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)
- [Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/)
- [Transition Evaluation and Priority](https://opsive.com/support/documentation/state-designer/concepts/transition-evaluation-and-priority/)
- [Variables](https://opsive.com/support/documentation/state-designer/variables/)
- [Subgraphs](https://opsive.com/support/documentation/state-designer/subgraphs/)

---

<a id="page-state-designer-referencing-scene-objects"></a>

# Referencing Scene Objects

[View this page online](https://opsive.com/support/documentation/state-designer/referencing-scene-objects/)

Assign a scene object at runtime when a reusable prefab, Subgraph, or Project variable needs to work with an object from the current scene. This commonly applies to targets, managers, spawn points, cameras, and other references that differ between scenes or agent instances.

## In the editor

While testing a scene instance, an Action or Shared Variable can reference a scene object directly. In this example, the FollowTarget Action uses the Ball GameObject as its Target.

![The FollowTarget Action Inspector with the Ball GameObject assigned to its Target field.](https://opsive.com/wp-content/uploads/2026/03/FollowTargetGameObject.png?v=960a45e2ecba)

The direct reference cannot remain when the agent or graph is stored as a project-level asset. Unity does not allow prefabs, Subgraphs, or Project variables to serialize references to objects that exist only in a scene.

## Set up the reference

1. Create a GameObject Shared Variable for the scene object.
2. Assign that Shared Variable to each State or Action field that needs the object.
3. Test the graph with a scene object assigned directly.
4. Before reusing the graph from a prefab or Subgraph, choose how the scene value will be supplied at runtime.

Use one of these supported approaches:

- Add an Action that finds the object with `GameObject.Find` or the project's own retrieval system.
- Place the State Machine component in the scene and use a [Subgraph Reference override](https://opsive.com/support/documentation/state-designer/concepts/states/subgraph-reference/) to supply the scene value to a reusable Subgraph.
- Assign the Shared Variable from an [initialization script](https://opsive.com/support/documentation/state-designer/variables/accessing-variables/).

There is no single required approach. Choose the one that best matches how the project creates agents and owns scene references.

## How it runs

A reusable prefab or Subgraph stores its graph data without a direct scene-object reference, and a Project variable also cannot hold that scene reference. At runtime, the selected setup resolves the scene object and assigns it to the Shared Variable. States and Actions that reference that same variable then receive the resolved object.

## Verify the reference

1. Create or instantiate the reusable agent in the scene.
2. Run the initialization, override, or lookup that assigns the target.
3. Confirm in Play Mode that the Shared Variable contains the expected scene object.
4. Confirm that the FollowTarget Action follows the assigned object rather than reporting a missing reference.

## Supported caveats

- A direct scene reference can work while testing a scene instance and then disappear when the object becomes a prefab or another project-level asset.
- Prefabs, Subgraphs, and Project variables cannot serialize scene-object references because the referenced object belongs to a scene.
- Runtime assignment must occur before a State or Action tries to use the value.

## Related pages

- [Accessing Variables](https://opsive.com/support/documentation/state-designer/variables/accessing-variables/)
- [Variable Scope](https://opsive.com/support/documentation/state-designer/variables/scope/)
- [Subgraphs](https://opsive.com/support/documentation/state-designer/subgraphs/)
- [Subgraph Reference](https://opsive.com/support/documentation/state-designer/concepts/states/subgraph-reference/)
- [GameObject Action](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-action/)

---

<a id="page-state-designer-save-load"></a>

# Save/Load

[View this page online](https://opsive.com/support/documentation/state-designer/save-load/)

Save a State Machine when the player should be able to return to the same active state and variable values later. Use StateMachine.Save and StateMachine.Load for one State Machine, SaveManager for several State Machines in one file, or raw SaveData when State Designer needs to participate in a larger game save.

## Save one State Machine

1. Assign the State Machine that should be saved.
2. Choose the file location.
3. Call Save at the desired checkpoint and Load when that checkpoint should be restored.

The following component saves and loads one State Machine:

```csharp
using Opsive.StateDesigner.Runtime;
using Opsive.StateDesigner.Runtime.Utility;
using UnityEngine;

public class Saver : MonoBehaviour
{
    [Tooltip("The state machine that should be saved.")]
    public StateMachine m_StateMachine;
    [Tooltip("The location that the state machine should be saved.")]
    public string m_SaveLocation = "Assets/StateMachine.save";

    /// <summary>
    /// Saves the state machine.
    /// </summary>
    public void Save()
    {
        m_StateMachine.Save(m_SaveLocation, SaveManager.VariableSaveScope.GameObjectVariables | SaveManager.VariableSaveScope.SceneVariables); // Saves the state machine and the GameObject/scene variables.
    }

    /// <summary>
    /// Restores the state machine.
    /// </summary>
    public void Load()
    {
        m_StateMachine.Load(m_SaveLocation);
    }
}
```

Graph variables are always included. The second Save parameter selects additional variable scopes; this example also saves GameObject and Scene variables.

## Save multiple State Machines

Use SaveManager when several State Machines should be saved to and restored from the same file. Assign the State Machines to the array, then pass the same array and file location to SaveManager.Save and SaveManager.Load.

```csharp
using Opsive.StateDesigner.Runtime;
using Opsive.StateDesigner.Runtime.Utility;
using UnityEngine;

public class Saver : MonoBehaviour
{
    [Tooltip("The state machines that should be saved.")]
    public StateMachine [] m_StateMachines;
    [Tooltip("The location that the state machines should be saved.")]
    public string m_SaveLocation = "Assets/StateMachine.save";

    /// <summary>
    /// Saves the state machine.
    /// </summary>
    public void Save()
    {
        SaveManager.Save(m_StateMachines, m_SaveLocation, SaveManager.VariableSaveScope.GameObjectVariables | SaveManager.VariableSaveScope.SceneVariables); // Saves the state machine and the GameObject/scene variables.
    }

    /// <summary>
    /// Restores the state machine.
    /// </summary>
    public void Load()
    {
        SaveManager.Load(m_StateMachines, m_SaveLocation);
    }
}
```

## Include State Machine data in another save

StateMachine.Save can also return raw SaveData. This is useful when State Machine state belongs inside an existing game-save structure rather than its own file. The following example stores the State Machine data with the agent position and rotation.

See the SaveLoad sample scene for a working example.

```csharp

    /// <summary>
    /// Stores all of the agent save data in one structure.
    /// </summary>
    private struct AgentSaveData
    {
        public SaveData StateMachineSaveData; // The state machine save data.
        public Vector3 Position; // The Transform position.
        public Quaternion Rotation; // The Transform rotation.
    }

    /// <summary>
    /// Save the agent state.
    /// </summary>
    public void Save()
    {
        var saveData = m_StateMachine.Save();
        if (!saveData.HasValue) {
            return;
        }

        // Create the data structure which contains all of the values that should be saved.
        var agentSaveData = new AgentSaveData() { StateMachineSaveData = saveData.Value, Position = m_Transform.position, Rotation = m_Transform.rotation };

        if (File.Exists(m_SaveLocation)) {
            File.Delete(m_SaveLocation);
        }
        try {
            if (!Directory.Exists(Path.GetDirectoryName(m_SaveLocation))) {
                Directory.CreateDirectory(Path.GetDirectoryName(m_SaveLocation));
            }
            var fileStream = File.Create(m_SaveLocation);
            using (var streamWriter = new StreamWriter(fileStream)) {
                streamWriter.Write(JsonUtility.ToJson(agentSaveData));
            }
            fileStream.Close();
        } catch (System.Exception e) {
            Debug.LogException(e);
            return;
        }
    }

    /// <summary>
    /// Load the agent state.
    /// </summary>
    public void Load()
    {
        if (!File.Exists(m_SaveLocation)) {
            return;
        }

        AgentSaveData agentSaveData;
        var fileStream = File.Open(m_SaveLocation, FileMode.Open);
        using (var streamReader = new StreamReader(fileStream)) {
            var fileData = streamReader.ReadToEnd();
            agentSaveData = JsonUtility.FromJson<AgentSaveData>(fileData);
        }
        fileStream.Close();

        // Restore the values.
        m_StateMachine.Load(agentSaveData.StateMachineSaveData);

        m_Transform.SetPositionAndRotation(agentSaveData.Position, agentSaveData.Rotation);
}
```

## How it runs

Saving records the current State Machine state and its graph variables. The variable-scope flags can include GameObject and Scene variables as well. Loading from the same file or SaveData restores those saved values and returns the State Machine to the saved state.

SaveManager applies the same process to an array of State Machines in one file. In the raw-data example, StateMachine.Save returns nullable SaveData, which is placed beside the agent transform data and serialized as one structure. Loading restores the State Machine data first, then the transform.

## Verify a restore

1. Run the State Machine until it reaches a recognizable state and set a known graph variable value.
2. Save, then allow the State Machine and variable to change.
3. Load the save and confirm that the saved state and graph variable value return.
4. If GameObject or Scene scopes were included, confirm those selected variable values also return.
5. For the raw-data example, also confirm that the agent position and rotation are restored.

## Supported caveats

- Graph variables are always saved; other scopes must be selected with VariableSaveScope flags.
- The raw-data example stops if StateMachine.Save returns no value or if the requested file does not exist.
- Custom Actions and Conditions that hold additional runtime state must implement their supported save/load callbacks when that state needs to persist.

## Related pages

- [State Machine API](https://opsive.com/support/documentation/state-designer/api/)
- [Variables](https://opsive.com/support/documentation/state-designer/variables/)
- [Variable Scope](https://opsive.com/support/documentation/state-designer/variables/scope/)
- [GameObject Action save/load](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-action/)
- [GameObject Condition save/load](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-condition/)

---

<a id="page-state-designer-extending-the-editor"></a>

# Extending the Editor

[View this page online](https://opsive.com/support/documentation/state-designer/extending-the-editor/)

State Designer can be extended when a custom state, action, condition, field, or attribute needs a clearer editor experience. Choose the extension point based on whether the additional interface belongs in an inspector or directly on a graph node.

## Choose an extension point

- [Control Types](https://opsive.com/support/documentation/state-designer/extending-the-editor/control-types/) are useful when a custom value or attribute needs its own field in an inspector.
- [Node Views](https://opsive.com/support/documentation/state-designer/extending-the-editor/node-views/) are useful when a node should display additional information or status directly in the graph.

---

<a id="page-state-designer-extending-the-editor-control-types"></a>

# Control Types

[View this page online](https://opsive.com/support/documentation/state-designer/extending-the-editor/control-types/)

A Control Type changes how a value or attribute is presented in the State Designer editor. Create one when the default field is not clear enough for your project, such as when a value needs a purpose-built selector, a compact toggle, additional layout, or a control that stays synchronized with another editor value.

Control Types affect the authoring interface only. They do not change how the state machine behaves at runtime.

## What changes in the editor

A **Type Control** draws the editor field for a C# type. The bool example on this page presents a boolean value as a labeled toggle. The same pattern can support a project-specific data type or a more complex value such as a Shared Variable.

An **Attribute Control** changes the interface for a field carrying a particular C# attribute. The Space example adds the amount of vertical space specified by `[Space]` while leaving the field's normal Type Control available.

State Designer uses these controls in places such as state and Shared Variable inspectors. The control system can also provide content for other editor areas, including a node view.

## Choose the extension point

- Create a **Type Control** when every field of a particular C# type needs the same editor interface.
- Create an **Attribute Control** when the interface should change only for fields marked with a particular attribute.
- Set an Attribute Control's `OverrideTypeControl` to `true` only when it should replace the field's Type Control. Return `false` when both controls should contribute to the interface.

**Cross-product note:** Control Types belong to the shared Opsive editor system. A control may also affect installed Opsive editors such as Ultimate Character Controller, Ultimate Inventory System, or Behavior Designer. The examples below are used here for State Designer; verify a project-specific control in every Opsive editor that can display its target type or attribute.

## Author a Type Control

1. Place the control script in an editor-only assembly.
2. Add `[ControlType]` with the C# type that the control represents.
3. Derive from `TypeControlBase`.
4. Set `UseLabel` according to whether State Designer should draw a field label.
5. Implement `GetControl` and return the required UIElements control.
6. Send user changes through `input.OnChangeEvent` and restore the previous value when the change is rejected.
7. Use `BindingUpdater` when the displayed value can change outside this control.

The following implementation draws a bool as a toggle:

```csharp
using Opsive.Shared.Editor.UIElements.Controls.Types;
using UnityEngine.UIElements;

[ControlType(typeof(bool))]
public class BoolControl : TypeControlBase
{
    /// <summary>
    /// Does the control use a label?
    /// </summary>
    public override bool UseLabel { get { return true; } }

    /// <summary>
    /// Returns the control that should be used for the specified ControlType.
    /// </summary>
    /// <param name="input">The input to the control.</param>
    /// <returns>The created control.</returns>
    protected override VisualElement GetControl(TypeControlInput input)
    {
        var toggle = new Toggle();
        toggle.value = (bool)input.Value;
        // Ensure the control is kept up to date as the value changes.
        if (input.Field != null) {
            System.Action<object> onBindingUpdateEvent = (object newValue) => toggle.SetValueWithoutNotify((bool)newValue);
            toggle.RegisterCallback<AttachToPanelEvent>(c =>
            {
                BindingUpdater.AddBinding(input.Field, input.ArrayIndex, input.Target, onBindingUpdateEvent);
            });
            toggle.RegisterCallback<DetachFromPanelEvent>(c =>
            {
                BindingUpdater.RemoveBinding(onBindingUpdateEvent);
            });
        }
        toggle.RegisterValueChangedCallback(c =>
        {
            if (!input.OnChangeEvent(c.newValue)) {
                toggle.SetValueWithoutNotify(c.previousValue);
            }
            c.StopPropagation();
        });
        return toggle;
    }
}
```

`[ControlType(typeof(bool))]` registers the target type. `UseLabel` keeps the field label visible, and `BindingUpdater` refreshes the persistent UIElements control when another part of the editor changes the value.

## Author an Attribute Control

1. Place the control script in an editor-only assembly.
2. Add `[ControlType]` with the attribute type.
3. Derive from `AttributeControlBase`.
4. Decide whether the attribute should replace the normal Type Control with `OverrideTypeControl`.
5. Set `UseLabel`, then implement `GetControl` and return the additional UIElements content.

This implementation reads Unity's `[Space]` attribute and draws a VisualElement with the requested height:

```csharp
using Opsive.Shared.Editor.UIElements.Controls.Attributes;
using System.Reflection;
using UnityEngine.UIElements;

[ControlType(typeof(UnityEngine.SpaceAttribute))]
public class SpaceAttributeControl : AttributeControlBase
{
    /// <summary>
    /// Does the attribute override the type control?
    /// </summary>
    public override bool OverrideTypeControl { get { return false; } }

    /// <summary>
    /// Does the control use a label?
    /// </summary>
    public override bool UseLabel { get { return false; } }

    /// <summary>
    /// Returns the attribute control that should be used for the specified AttributeControlType.
    /// </summary>
    /// <param name="input">The input to the control.</param>
    /// <returns>The created control.</returns>
    protected override VisualElement GetControl(AttributeControlInput input)
    {
        var spaceAttribute = input.Field.GetCustomAttribute<UnityEngine.SpaceAttribute>();
        if (spaceAttribute == null) {
            return null;
        }

        var visualElement = new VisualElement();
        visualElement.style.height = spaceAttribute.height;
        return visualElement;
    }
}
```

`OverrideTypeControl` is `false`, so the spacing is added without removing the field's normal control. `UseLabel` is also `false` because the spacing itself does not need a label.

## Verify the editor result

After Unity compiles the editor assembly, open State Designer and select an element containing the target type or attribute. Confirm that the custom control appears in the Inspector, accepts an edit, and leaves the underlying field with the new value.

For a Type Control that uses `BindingUpdater`, change the same value from another supported editor surface and confirm that the visible control refreshes without closing and reopening the Inspector. For an Attribute Control, confirm both the attributed layout and whether the normal Type Control is present according to `OverrideTypeControl`.

The bool and Space controls shown above illustrate the registration pattern for standard types that already have editor behavior. Give a project-specific control its own class name and register only the type or attribute that it is intended to customize.

## Related pages

- [Extending the Editor](https://opsive.com/support/documentation/state-designer/extending-the-editor/) helps choose an editor extension point.
- [Node Views](https://opsive.com/support/documentation/state-designer/extending-the-editor/node-views/) adds custom information directly to State Designer graph nodes.
- [GameObject Action](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-action/) shows how to author configurable state behavior.
- [GameObject Condition](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-condition/) shows how to author configurable transition checks.
- [Blackboard](https://opsive.com/support/documentation/state-designer/concepts/blackboard/) shows Shared Variables in the State Designer editor.

---

<a id="page-state-designer-extending-the-editor-node-views"></a>

# Node Views

[View this page online](https://opsive.com/support/documentation/state-designer/extending-the-editor/node-views/)

Use a custom Node View when important information should be visible directly on a State Designer graph node without first selecting it. A Node View can show a compact configuration summary or runtime status while leaving the full editable controls in the Element Inspector.

## What appears in the editor

The built-in Action State view demonstrates this pattern by listing its contained Actions inside the node. The additional content helps identify the state's behavior while the whole graph remains visible.

![An Action State node lists its contained Actions directly in the State Designer graph.](https://opsive.com/wp-content/uploads/2026/03/ActionStateNodeView.png?v=b2ae33f34000)

Use a [Control Type](https://opsive.com/support/documentation/state-designer/extending-the-editor/control-types/) instead when a value needs a custom editable field in an inspector. A Node View is most useful for information that should remain visible on the graph.

## Add a custom Node View

1. Choose the state type that needs additional graph content.
2. Create the view script in an editor-only assembly or an `Editor` folder.
3. Apply `ControlType` for the state type and derive the view from `StateNodeView` so the standard State Designer node content and runtime highlighting remain available.
4. Override `AddNodeView`, call the base implementation, and add the required UIElements to `parent`.

This example adds the configured repeat behavior to a Repeater node:

```csharp
using Opsive.GraphDesigner.Editor;
using Opsive.Shared.Editor.UIElements.Controls;
using Opsive.StateDesigner.Editor.Controls.NodeViews;
using Opsive.StateDesigner.Runtime.States;
using UnityEngine.UIElements;

[ControlType(typeof(Repeater))]
public class RepeaterNodeView : StateNodeView
{
    public override void AddNodeView(GraphWindow graphWindow, VisualElement parent, object node)
    {
        base.AddNodeView(graphWindow, parent, node);

        var repeater = node as Repeater;
        if (repeater == null) {
            return;
        }

        var repeatsForever = repeater.RepeatForever != null && repeater.RepeatForever.Value;
        var repeatCount = repeater.RepeatCount != null ? repeater.RepeatCount.Value : 0;
        parent.Add(new Label(repeatsForever ? "Repeats forever" : $"Repeats: {repeatCount}"));
    }
}
```

`AddNodeView` receives the runtime node represented by the editor node. Casting it to the registered state type gives the view access to that state's configuration without searching by index.

## Keep runtime information current

The example reads configuration when the view is created. If a view displays information that changes during Play Mode, register an update callback when the element receives `AttachToPanelEvent` and unregister it on `DetachFromPanelEvent`. State Designer's built-in view uses `GraphEventType.WindowUpdate` for this purpose.

When reading State Designer runtime buffers, use the node's `RuntimeIndex` rather than its editor `Index`. Runtime ordering can differ when a graph contains injected or referenced subgraphs.

## Verify the result

After Unity compiles the editor script, add a Repeater state to a graph. Confirm that the node still shows its normal State Designer content and now also displays either **Repeats forever** or the configured repeat count.

Enter Play Mode and confirm that the normal active-state highlighting still works. If the additional label does not appear, check that the script is in an editor-only assembly, `ControlType` targets the intended state class, and `AddNodeView` adds the element to `parent`.

## Related pages

- [Extending the Editor](https://opsive.com/support/documentation/state-designer/extending-the-editor/)
- [Control Types](https://opsive.com/support/documentation/state-designer/extending-the-editor/control-types/)
- [States](https://opsive.com/support/documentation/state-designer/concepts/states/)

---

<a id="page-state-designer-api"></a>

# API

[View this page online](https://opsive.com/support/documentation/state-designer/api/)

The `StateMachine` component is the main code entry point for a State Designer graph. Use its API when another script needs to control execution, inspect runtime state, respond to lifecycle changes, access Shared Variables, or save and restore the graph. If the behavior can be configured directly in the graph and Inspector, code is not required.

## Start, stop, pause, or restart a graph

- `StartGraph()` starts the graph and returns whether it started. Calling it on a paused graph resumes execution.
- `StopGraph()` stops the graph. Pass `true` to its `pause` parameter when the graph should be resumable.
- `RestartGraph()` stops and starts an active graph.
- `Tick()` requests one evaluation when the State Machine's Update Mode is **Manual**. The evaluation occurs the next time the DOTS system group updates rather than immediately inside the call.

Use these methods for external controls such as enabling an agent, pausing gameplay, restarting a scenario, or advancing a turn-based simulation.

## Query nodes and execution status

Read `StateMachine.Status` when UI or debugging code needs the status of the state connected to the Start node. It returns `Inactive`, `Queued`, `Running`, or `Finished`.

Use `GetNode(Type)` to find a logic node and `GetEventNode(Type)` to find an event node and its index. Both lookups can return a null node, so check the result before using it. After runtime Subgraph selection changes, `ReevaluateSubgraphReferences()` rebuilds the injected Subgraph content and restarts the graph.

## Respond to lifecycle events

Subscribe to `OnStateMachineStarted`, `OnStateMachineStopped`, or `OnStateMachineDestroyed` when another system must react to graph execution. The save/load callbacks `OnWillSave`, `OnDidSave`, `OnWillLoad`, and `OnDidLoad` allow surrounding code to coordinate with persistence.

## Read and update variables

`GetVariable` returns a Shared Variable by name. The overloads without a scope use Graph scope; the scoped overloads can request another supported `SharedVariable.SharingScope`. Prefer `GetVariable<T>` when the expected value type is known.

Use `SetVariableValue<T>` to update a value. Its return value reports whether the matching variable was found and set. Keep the name, type, and scope consistent with the variable configured in State Designer.

## Save and restore a graph

`Save` writes one State Machine to a file and always includes Graph variables. Its variable-scope parameter can include additional scopes. `Load` accepts either a file path or existing `SaveManager.SaveData`; both overloads can run a callback after variables are restored.

## API reference

The following signatures cover the `StateMachine` methods described on this page:

```csharp
/// <summary>
/// Starts the state machine graph.
/// </summary>
/// <returns>True if the graph was started.</returns>
bool StartGraph()

/// <summary>
/// Returns the logic node of the specified type.
/// </summary>
/// <param name="type">The type of node to retrieve.</param>
/// <returns>The node of the specified type (can be null).</returns>
ILogicNode GetNode(Type type)

/// <summary>
/// Returns the event node of the specified type.
/// </summary>
/// <param name="type">The type of event node to retrieve.</param>
/// <returns>The event node and its index (node can be null).</returns>
(IEventNode, ushort) GetEventNode(Type type)

/// <summary>
/// Ticks the state machine. UpdateMode must be Manual.
/// </summary>
void Tick()

/// <summary>
/// Reevaluates SubgraphReference nodes by calling EvaluateSubgraphs.
/// </summary>
void ReevaluateSubgraphReferences()

/// <summary>
/// Stops or pauses the state machine.
/// </summary>
/// <param name="pause">Should the graph be paused?</param>
/// <returns>True if the graph was stopped or paused.</returns>
bool StopGraph(bool pause = false)

/// <summary>
/// Restarts the state machine.
/// </summary>
/// <returns>True if the graph was restarted.</returns>
bool RestartGraph()

/// <summary>
/// Returns the SharedVariable with the specified name (Graph scope).
/// </summary>
SharedVariable GetVariable(PropertyName name)

/// <summary>
/// Returns the SharedVariable with the specified name and scope.
/// </summary>
SharedVariable GetVariable(PropertyName name, SharedVariable.SharingScope scope)

/// <summary>
/// Returns the typed SharedVariable with the specified name (Graph scope).
/// </summary>
SharedVariable<T> GetVariable<T>(PropertyName name)

/// <summary>
/// Returns the typed SharedVariable with the specified name and scope.
/// </summary>
SharedVariable<T> GetVariable<T>(PropertyName name, SharedVariable.SharingScope scope)

/// <summary>
/// Sets a SharedVariable value (Graph scope).
/// </summary>
bool SetVariableValue<T>(PropertyName name, T value)

/// <summary>
/// Sets a SharedVariable value with explicit scope.
/// </summary>
bool SetVariableValue<T>(PropertyName name, T value, SharedVariable.SharingScope scope)

/// <summary>
/// Saves the state machine to the specified file path.
/// </summary>
/// <param name="filePath">Destination file path.</param>
/// <param name="variableSaveScope">Which variable scopes to save (Graph variables are always saved).</param>
/// <returns>True if save succeeded.</returns>
bool Save(string filePath, SaveManager.VariableSaveScope variableSaveScope = 0)

/// <summary>
/// Loads the state machine from a file path.
/// </summary>
/// <param name="filePath">Source file path.</param>
/// <param name="afterVariablesRestored">Optional callback after variable restore.</param>
/// <returns>True if load succeeded.</returns>
bool Load(string filePath, Action<StateMachine> afterVariablesRestored = null)

/// <summary>
/// Loads the state machine from SaveData.
/// </summary>
/// <param name="saveData">In-memory save data.</param>
/// <param name="afterVariablesRestored">Optional callback after variable restore.</param>
/// <returns>True if load succeeded.</returns>
bool Load(SaveManager.SaveData saveData, Action<StateMachine> afterVariablesRestored = null)
```

## Manual update mode

When Update Mode is **Manual**, the graph does not request evaluation automatically each frame. Start it normally, then call `Tick()` whenever the simulation should advance:

```csharp
using Opsive.StateDesigner.Runtime;
using UnityEngine;

public class ManualTickExample : MonoBehaviour
{
    [SerializeField] private StateMachine m_StateMachine;

    private void Start()
    {
        m_StateMachine.StartGraph();
    }

    public void AdvanceTurn()
    {
        m_StateMachine.Tick();
    }
}
```

This pattern is useful for turn-based or deterministic step-driven simulations. A tick is queued for the next DOTS system-group update rather than completed during the `Tick()` call.

## Event callback names

Flow lifecycle:

```csharp
OnStateMachineStarted
OnStateMachineStopped
OnStateMachineDestroyed
```

Save/load lifecycle:

```csharp
OnWillSave
OnDidSave
OnWillLoad
OnDidLoad
```

The first group reports graph execution changes. The second group surrounds save and load operations and reports their outcomes through the callback signatures exposed by `StateMachine`.

## Verify the integration

In Play Mode, verify only the parts your script uses:

1. Call `StartGraph()` and confirm that it returns `true` and `Status` reflects the Start branch's execution.
2. If using Manual Update Mode, confirm that the graph advances after each requested tick and does not evaluate automatically between ticks.
3. Subscribe and unsubscribe from the selected lifecycle callback, then confirm it fires during the matching operation.
4. Read a known Shared Variable, update it with the matching name, type, and scope, and confirm that `SetVariableValue<T>` returns `true`.
5. If saving, change the graph state after `Save`, call `Load`, and confirm that the saved state and variables return.

Check null node or variable lookups before use. A failed start, stop, variable update, save, or load is reported by its `bool` return value.

## Related pages

- [Getting Started](https://opsive.com/support/documentation/state-designer/getting-started/)
- [Accessing Variables](https://opsive.com/support/documentation/state-designer/variables/accessing-variables/)
- [Events](https://opsive.com/support/documentation/state-designer/events/)
- [Save/Load](https://opsive.com/support/documentation/state-designer/save-load/)
- [Subgraphs](https://opsive.com/support/documentation/state-designer/subgraphs/)
- [Entity Baking](https://opsive.com/support/documentation/state-designer/entity-baking/)

---

<a id="page-state-designer-networking"></a>

# Networking

[View this page online](https://opsive.com/support/documentation/state-designer/networking/)

Run State Designer on the server or whichever peer has authority, then send the resulting gameplay changes to the other clients. Use this pattern when the state machine should make decisions in one authoritative place while the networking solution synchronizes outcomes such as transforms, animations, or events.

The state machine itself does not need to know which networking package the project uses, and clients do not need a synchronized copy of its execution state.

## Prerequisites and authority

Choose how the networking implementation identifies the authoritative instance. In a server-authoritative game this is the server. In a client-authoritative setup it is the client that owns the decision.

Confirm that the networking layer already sends the results produced by the state machine to the other clients. For example, when a Play Animation state runs on the authority, the clients receive the animation result rather than running the same decision graph independently.

## GameObject setup

Enable the State Machine component only on the authoritative instance. Replace `IsServer()` with the authority check provided by the project's networking implementation:

```csharp
public class StateMachineEnabler : MonoBehaviour
{
    [Tooltip("A reference to the state machine.")]
    public StateMachine m_StateMachine;

    private void Awake()
    {
        m_StateMachine.enabled = IsServer();
    }
}
```

This keeps the State Designer graph disabled on non-authoritative clients while allowing the networking layer to deliver the results they need to display.

## Entity setup

For a baked Entity State Machine, call `StateMachine.StartBakedStateMachine` only on the authoritative instance. Extend the spawn data with the authority information supplied by the networking implementation, then start each entity created from the baked prefab:

```csharp
public partial struct EntitySpawnerSystem : ISystem
{
    /// <summary>
    /// Sets the system requirements.
    /// </summary>
    /// <param name="state">The current SystemState.</param>
    private void OnCreate(ref SystemState state)
    {
        state.RequireForUpdate<SpawnData>();
    }

    /// <summary>
    /// Spawns the entities.
    /// </summary>
    /// <param name="state">The current SystemState.</param>
    private void OnUpdate(ref SystemState state)
    {
        state.Enabled = false;

        var spawner = SystemAPI.ManagedAPI.GetSingleton<SpawnData>();
        var entities = state.EntityManager.Instantiate(spawner.Prefab, 100, Allocator.Temp);

        // Any custom setup for each entity. This can include adding new components, enabling components, setting entity data, etc.

        // IsServer is supplied by the networking implementation.
        if (spawner.IsServer) {
            for (int i = 0; i < entities.Length; ++i) {
                StateMachine.StartBakedStateMachine(World.DefaultGameObjectInjectionWorld, entities[i]);
            }
        }
    }
}
```

Do not call `StartBakedStateMachine` for the client instances. See [Entity Baking](https://opsive.com/support/documentation/state-designer/entity-baking/) for the complete prefab and spawning workflow that this authority check extends.

## Network behavior

Only the authoritative State Machine evaluates states and transitions. The networking implementation then synchronizes the visible or gameplay result. This keeps State Designer independent of the networking package and avoids running the same decision flow separately on every client.

The same division applies to server-authoritative and client-authoritative projects: one instance owns the decisions, and the other peers receive their results.

## Verify the result

Run a server and client together and confirm that:

- The State Machine component is enabled on the authoritative GameObject and disabled on the non-authoritative copy.
- A state change produces the expected synchronized result on the clients.
- A baked Entity State Machine starts only where the authority check passes.

If the graph runs on every peer, verify the implementation of `IsServer()` or the equivalent authority check. If clients do not show the result, verify the networking code that synchronizes the transform, animation, event, or other output; State Designer does not perform that synchronization itself.

## Related pages

- [Entity Baking](https://opsive.com/support/documentation/state-designer/entity-baking/)
- [Events](https://opsive.com/support/documentation/state-designer/events/)
- [Overview](https://opsive.com/support/documentation/state-designer/overview/)

---

<a id="page-state-designer-integrations"></a>

# Integrations

[View this page online](https://opsive.com/support/documentation/state-designer/integrations/)

Integrations add Actions and Conditions that command or inspect another gameplay system while State Designer owns the State and transition flow.

## Install an integration

Download the matching bridge from [Opsive Downloads](https://opsive.com/downloads/), then import it after the third-party asset. Bridges are separate downloads and appear in the project only after import. Provider-maintained exceptions are identified on their integration pages.

Open **Tools > Opsive > State Designer > Integrations** to review the installed entry, then search the State Palette for an Action or Condition named on its page below.

## Available integrations

| Integration | What it adds |
| --- | --- |
| [Animal Controller](https://opsive.com/support/documentation/state-designer/integrations/animal-controller/)<br>[Asset Store](https://assetstore.unity.com/packages/tools/animation/animal-controller-malbers-character-controller-148877?aid=1100lGdc) | Malbers animal movement, targeting, stance, Mode, reaction, weapons, aim, and controller Conditions. |
| [Atlas](https://opsive.com/support/documentation/state-designer/integrations/atlas/)<br>[Atlas page](https://opsive.com/atlas/) | Ask, plan, generate, modify, correct, review, and apply validated GameObject or ECS Actions and Conditions. |
| [Behavior Designer Pro](https://opsive.com/support/documentation/state-designer/integrations/behavior-designer-pro/)<br>[Asset Store](https://assetstore.unity.com/packages/tools/visual-scripting/behavior-designer-pro-dots-powered-behavior-trees-298743?aid=1100lGdc) | Start, stop, inspect, and synchronize behavior trees, with reciprocal Behavior Designer tasks. |
| [Curvy Splines](https://opsive.com/support/documentation/state-designer/integrations/curvy-splines/)<br>[Asset Store](https://assetstore.unity.com/packages/tools/utilities/curvy-splines-8-212532?aid=1100lGdc) | Create and query splines, control points, nearest positions, segment values, and alignment. |
| [Dialogue System](https://opsive.com/support/documentation/state-designer/integrations/dialogue-system/)<br>[Asset Store](https://assetstore.unity.com/packages/tools/behavior-ai/dialogue-system-for-unity-11672?aid=1100lGdc) | Conversations, barks, sequences, Lua, dialogue variables, and quest state nodes. |
| [DOTS Survivors](https://opsive.com/support/documentation/state-designer/integrations/dots-survivors/)<br>[Provider documentation](https://survivors.tmg.dev/) | A provider-maintained ECS-agent bridge whose compatibility must be confirmed with its provider. |
| [Essential Kit](https://opsive.com/support/documentation/state-designer/integrations/essential-kit/)<br>[Asset Store](https://assetstore.unity.com/packages/slug/301752?aid=1100lGdc) | Actions and event Conditions for supported mobile services, interface, billing, cloud, notifications, sharing, and web views. |
| [Feel](https://opsive.com/support/documentation/state-designer/integrations/feel/)<br>[Asset Store](https://assetstore.unity.com/packages/tools/particles-effects/feel-183370?aid=1100lGdc) | Play one feedback or an MMF Player feedback sequence from a State. |
| [Juicy Actions](https://opsive.com/support/documentation/state-designer/integrations/juicy-actions/)<br>[Asset Store](https://assetstore.unity.com/packages/slug/269711?aid=1100lGdc) | Coordinate Action Executors and State Machines in either direction, including status and variable transfer. |
| [Love/Hate](https://opsive.com/support/documentation/state-designer/integrations/love-hate/)<br>[Asset Store](https://assetstore.unity.com/packages/tools/ai/love-hate-33063?aid=1100lGdc) | Faction, affinity, deed, rumor, emotion, personality, and relationship nodes. |
| [PlayMaker](https://opsive.com/support/documentation/state-designer/integrations/playmaker/)<br>[Asset Store](https://assetstore.unity.com/packages/tools/visual-scripting/playmaker-368?aid=1100lGdc) | Coordinate a PlayMaker finite state machine and State Machine through the current bridge route. |
| [Quest Machine](https://opsive.com/support/documentation/state-designer/integrations/quest-machine/)<br>[Asset Store](https://assetstore.unity.com/packages/tools/game-toolkits/quest-machine-39834?aid=1100lGdc) | Quest generation, state, counters, messages, spawners, alerts, heads-up display, Journal interface, and dialogue nodes. |
| [Sensor Toolkit 2](https://opsive.com/support/documentation/state-designer/integrations/sensor-toolkit-2/)<br>[Asset Store](https://assetstore.unity.com/packages/slug/317234?aid=1100lGdc) | Sensor Actions and Conditions for detections, signals, obstruction, seeking, and destinations. |
| [Simple Waypoint System](https://opsive.com/support/documentation/state-designer/integrations/simple-waypoint-system/)<br>[Asset Store](https://assetstore.unity.com/packages/tools/animation/simple-waypoint-system-2506?aid=1100lGdc) | Path selection and start, pause, resume, stop, speed, waypoint, and Bezier operations. |
| [Ultimate Character Controller](https://opsive.com/support/documentation/state-designer/integrations/ultimate-character-controller/)<br>[Asset Store](https://assetstore.unity.com/packages/tools/game-toolkits/ultimate-character-controller-233710?aid=1100lGdc) | Control abilities, effects, items, health, attributes, State System state, aim, and events. |
| [Ultimate Inventory System](https://opsive.com/support/documentation/state-designer/integrations/ultimate-inventory-system/)<br>[Asset Store](https://assetstore.unity.com/packages/tools/game-toolkits/ultimate-inventory-system-166053?aid=1100lGdc) | Inspect or change Items, Currency, Item Actions, panels, interactions, and Version 1 saves. |

## Runtime ownership

State Designer owns the State and transition decision; the third-party system owns the operation requested by an Action or observed by a Condition. Do not let two systems drive the same Transform or output.

## Related pages

- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)
- [Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/)
- [Variables](https://opsive.com/support/documentation/state-designer/variables/)
- [Transition Evaluation and Priority](https://opsive.com/support/documentation/state-designer/concepts/transition-evaluation-and-priority/)
- [Debugging](https://opsive.com/support/documentation/state-designer/debugging/)

---

<a id="page-state-designer-integrations-animal-controller"></a>

# Animal Controller

[View this page online](https://opsive.com/support/documentation/state-designer/integrations/animal-controller/)


Use the [Animal Controller](https://assetstore.unity.com/packages/tools/animation/animal-controller-malbers-character-controller-148877?aid=1100lGdc) integration when States should drive a Malbers Animations animal, stance, mode, weapon, aim, target, or destination through the controller APIs.

## Install the integration

1. Download the current **Animal Controller** integration from [Opsive Downloads](https://opsive.com/downloads/).
2. Import `StateDesignerAnimalController.unitypackage`.
3. Confirm **Set Destination** appears in the State Palette.

## What the integration adds

- **Movement and targeting:** **Set Destination**, **Set Speed**, **Set Strafe**, **Set Target**, **Stop Movement**.
- **Animation and reaction:** **Play Mode**, **Play Stance**, **Play State**, **React**, **Activate Zone**.
- **Weapons:** **Attack Weapon**, **Equip Weapon**, **Unequip Weapon**, **Reload Weapon**, **Set Aim**.
- **Conditions:** **Is Aiming**, **Is Attacking**, **Is Reloading**.

## Build a first workflow

1. Verify the Animal Controller can move and play one Mode directly.
2. Use Patrol, Chase, and Attack States and assign movement Actions to their owners.
3. Use the supplied Conditions to leave Attack or Reload only when the controller reports completion.
4. Stop movement and clear the target on the exit path that owns those requests.

## Related pages

- [Integrations](https://opsive.com/support/documentation/state-designer/integrations/)
- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)
- [Variables](https://opsive.com/support/documentation/state-designer/variables/)
- [Debugging](https://opsive.com/support/documentation/state-designer/debugging/)

---

<a id="page-state-designer-integrations-atlas"></a>

# Atlas

[View this page online](https://opsive.com/support/documentation/state-designer/integrations/atlas/)

Atlas is the Opsive assistant for asking State Designer questions, planning a node, and generating validated GameObject or ECS Actions and Conditions inside Unity. Generated files remain previews until you explicitly apply them.

## Install and connect Atlas

Atlas requires **State Designer 1.3.0 or newer**.

1. Confirm the installed State Designer version is 1.3.0 or newer.
2. Download Atlas from the [Atlas page](https://opsive.com/atlas/) and import it into the State Designer project. Atlas is not available from the Opsive Downloads page.
3. Install the Codex desktop app or standalone Codex CLI on Windows or macOS and sign in with the subscription Atlas should use.
4. Open **Tools > Opsive > State Designer > Atlas**. State Designer can also open Atlas as a docked panel.
5. Select **Sign in**. Atlas opens a one-time browser page and checks the Opsive account for State Designer. Enter the Unity invoice only when the account has not already linked that purchase.
6. Return to Unity and confirm **State Designer** is the active Opsive asset.

No Atlas token or Codex credential is copied into Unity. Codex authentication remains on the local machine.

![Atlas presents validated State Designer files and their apply controls after completing a request.](https://opsive.com/wp-content/uploads/2026/08/sd-atlas-validated-files-editor.webp?v=9a2b932c8aea)

## Choose how Atlas should help

- **Ask** explains State Designer behavior or recommends an existing Action or Condition without creating a file.
- **Plan** produces a reviewable implementation plan before code generation.
- **Generate** creates GameObject or ECS Actions and Conditions that use the State Designer lifecycle.
- **Modify** changes a user-authored State object that you explicitly select.
- **Correct** uses real compiler diagnostics to repair and revalidate an earlier result.
- A complete saved plan can become a dependency-ordered, multi-file package. Incomplete batches remain previews until the full result is ready.

Atlas checks the installed API and existing built-in node catalog before inventing a new type. Prefer the built-in node when it already provides the complete behavior.

## Generate a first Action or Condition

1. Commit or back up the project and open a small State Machine used only for the test.
2. Ask for one visible responsibility, such as: `Generate a GameObject Condition that is true when a Shared Transform is within a configurable distance.`
3. Review whether the result should be an Action or Condition, GameObject or ECS, and whether its fields belong in Shared Variables.
4. Inspect the summary and full source. Use **Apply**, **Save as...**, **Copy**, or **Discard** deliberately.
5. Let Unity compile. Return the exact diagnostic through **Correct** when compilation fails.
6. Add the node to a test State or transition and verify entry, update/evaluation, exit, re-entry, and disabled-owner behavior.

For a multi-file result, inspect each file and destination before **Apply all**. Atlas preserves the planned folder structure and rolls back a failed batch write.

## Understand the visible controls

- **Active Opsive asset** selects State Designer when multiple supported Opsive products are installed.
- **Model** and **Effort** show only provider choices returned for the current connection.
- **New chat**, tabs, and **All chats** keep unrelated implementations separate.
- **Show work** expands progress detail; it does not apply code.
- **Apply**, **Save as...**, **Copy**, and **Discard** control each generated file.
- **Helpful**, **Not helpful**, **Retry request**, and **Resume package build** report quality or recover an interrupted request.
- The **Atlas** menu under **Tools > Opsive > State Designer** contains **Verbose Diagnostics**, a support tool that should normally remain disabled.

Atlas sends a bounded relevant API summary plus project files explicitly included for the request, not the whole Unity project. The [Atlas page](https://opsive.com/atlas/) describes the current provider and privacy boundary.

## Verify the generated node

1. Confirm the class derives from the intended GameObject or ECS Action/Condition base.
2. Add it through the State Palette and inspect every exposed field.
3. Run the State Machine and confirm the active State, transition result, and visible gameplay result agree.
4. Exit and re-enter the State to check cleanup and initialization.
5. Test the false/failure path, disabled owner, scene reload, and target build where relevant.
6. Commit the reviewed source as ordinary project code.

## Troubleshooting

| Symptom | Check | Fix |
| --- | --- | --- |
| State Designer is unavailable in the asset selector. | Confirm State Designer and its Action/Condition base types compiled. | Resolve the first Console error, then reopen Atlas. |
| The one-time page cannot verify ownership. | Check the Opsive account and linked Unity invoice for State Designer. | Use the owning account or enter the matching invoice on the connection page. |
| Atlas cannot start the local provider. | Check that Codex is installed and signed in locally. | Complete Codex sign-in, then retry from Unity. |
| The generated node exists but is absent from the State Palette. | Check compilation, namespace, abstract status, and the selected GameObject/ECS unit option. | Resolve compilation and search in the matching unit type. |
| A Condition has side effects or an Action owns a durable decision. | Check whether the requested responsibility uses the correct node kind. | Keep Conditions observational and move work into the State's Actions. |
| Re-entering a State preserves stale data. | Check generated initialization and cleanup lifecycle methods. | Send the reproducible behavior back for correction or update the reviewed source before use. |

## Related pages

- [Integrations](https://opsive.com/support/documentation/state-designer/integrations/)
- [GameObject Actions](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-action/)
- [GameObject Conditions](https://opsive.com/support/documentation/state-designer/new-nodes/gameobject-condition/)
- [Entity Baking](https://opsive.com/support/documentation/state-designer/entity-baking/)
- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)
- [Conditions](https://opsive.com/support/documentation/state-designer/concepts/conditions/)
- [Debugging](https://opsive.com/support/documentation/state-designer/debugging/)

---

<a id="page-state-designer-integrations-behavior-designer-pro"></a>

# Behavior Designer Pro

[View this page online](https://opsive.com/support/documentation/state-designer/integrations/behavior-designer-pro/)


Use the [Behavior Designer Pro](https://assetstore.unity.com/packages/tools/visual-scripting/behavior-designer-pro-dots-powered-behavior-trees-298743?aid=1100lGdc) integration when a finite state machine should start, stop, inspect, or exchange variables with a behavior tree without duplicating the tree as States.

## Install the integration

1. Download the current **Behavior Designer Pro** integration from [Opsive Downloads](https://opsive.com/downloads/).
2. Import `BehaviorDesignerStateDesigner.unitypackage`.
3. Confirm **Start Behavior Tree** appears in the State Palette.

## What the integration adds

- **State Designer nodes:** **Start Behavior Tree**, **Stop Behavior Tree**, **Is Behavior Tree Active**, **Compare Behavior Tree Status**, **Synchronize Behavior Tree Variables**.
- **Behavior Designer Pro tasks:** **Start State Machine**, **Stop State Machine**, **Is State Machine Active**, **Compare State Machine Status**, **Synchronize State Machine Variables**.

## Build a first workflow

1. Put a Behavior Tree component on the object that owns a reusable decision flow.
2. Add **Start Behavior Tree** to the entering State and assign that component.
3. Use **Compare Behavior Tree Status** on a transition or later State.
4. Synchronize only the Shared Variables that cross the graph boundary.
5. Stop or resume the tree deliberately when the State exits.

## Related pages

- [Integrations](https://opsive.com/support/documentation/state-designer/integrations/)
- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)
- [Variables](https://opsive.com/support/documentation/state-designer/variables/)
- [Debugging](https://opsive.com/support/documentation/state-designer/debugging/)

---

<a id="page-state-designer-integrations-curvy-splines"></a>

# Curvy Splines

[View this page online](https://opsive.com/support/documentation/state-designer/integrations/curvy-splines/)


Use the [Curvy Splines](https://assetstore.unity.com/packages/tools/utilities/curvy-splines-8-212532?aid=1100lGdc) integration when States or transitions need to create, query, align with, or update a Curvy spline and its control points.

## Install the integration

1. Download the current **Curvy Splines** integration from [Opsive Downloads](https://opsive.com/downloads/).
2. Import `StateDesignerCurvy.unitypackage`.
3. Confirm **Get Nearest Point** appears in the State Palette.

## What the integration adds

- **Spline nodes:** **Create Spline**, **Set Control Points**, **Get Control Points**, **Delete Control Points**, **Get Nearest Point**, **Get Segment Value**, **Get Value**, **Align To Spline**, **Is Initialized**.

## Build a first workflow

1. Create and initialize a Curvy spline.
2. Use **Is Initialized** before entering the movement State.
3. Store the nearest point or segment value in a Shared Variable.
4. Use **Align To Spline** or the project movement owner to produce visible motion.

## Related pages

- [Integrations](https://opsive.com/support/documentation/state-designer/integrations/)
- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)
- [Variables](https://opsive.com/support/documentation/state-designer/variables/)
- [Debugging](https://opsive.com/support/documentation/state-designer/debugging/)

---

<a id="page-state-designer-integrations-dialogue-system"></a>

# Dialogue System

[View this page online](https://opsive.com/support/documentation/state-designer/integrations/dialogue-system/)


Use the Pixel Crushers [Dialogue System](https://assetstore.unity.com/packages/tools/behavior-ai/dialogue-system-for-unity-11672?aid=1100lGdc) integration when a State should start or stop conversations and sequences, bark, run Lua, or read and write dialogue and quest values.

## Install the integration

1. Download the current **Dialogue System** integration from [Opsive Downloads](https://opsive.com/downloads/).
2. Import `StateDesignerDialogueSystem.unitypackage`.
3. Confirm **Start Conversation** appears in the State Palette.

## What the integration adds

- **Conversation:** **Start Conversation**, **Stop Conversation**, **Is Conversation Active**, **Bark**, **Start Sequence**, **Stop Sequence**.
- **Lua and variables:** **Run Lua**, **Is Lua True**, **Get Dialogue Bool Variable**, **Set Dialogue Bool Variable**, **Get Dialogue Float Variable**, **Set Dialogue Float Variable**, **Get Dialogue Int Variable**, **Set Dialogue Int Variable**, **Get Dialogue String Variable**, **Set Dialogue String Variable**.
- **Quests:** **Get Quest State**, **Set Quest State**, **Get Quest Entry State**, **Set Quest Entry State**.

## Build a first workflow

1. Verify one Dialogue System conversation starts directly.
2. Enter a Conversation State and run **Start Conversation**.
3. Use **Is Conversation Active** or the relevant callback Condition to remain in that State.
4. Read the resulting quest or dialogue value before selecting the next State.

## Related pages

- [Integrations](https://opsive.com/support/documentation/state-designer/integrations/)
- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)
- [Variables](https://opsive.com/support/documentation/state-designer/variables/)
- [Debugging](https://opsive.com/support/documentation/state-designer/debugging/)

---

<a id="page-state-designer-integrations-dots-survivors"></a>

# DOTS Survivors

[View this page online](https://opsive.com/support/documentation/state-designer/integrations/dots-survivors/)


Use the DOTS Survivors integration when that framework should run State Designer decisions for its ECS agents through the provider-maintained bridge.

## Install the integration

1. Open **Tools > Opsive > State Designer > Integrations**, select **DOTS Survivors**, and follow its provider-owned documentation route. Opsive does not distribute this bridge.
2. Confirm that the provider's expected Actions and Conditions appear and its sample opens.

## What the integration adds

The provider supplies the Actions and Conditions used to hand work between the two products. Inspect the installed selector and provider sample for the exact version-specific list.

## Build a first workflow

1. Install DOTS Survivors and verify its standalone ECS sample.
2. Open the provider documentation route from the State Designer Integrations window.
3. Add the provider bridge to a copy of the sample.
4. Verify one Entity changes State and retains valid component data.

## Package and support boundary

Because the provider controls this bridge, the package version, supported platforms, and exact node names can change independently of State Designer. Record the tested combination in the project before upgrading.

- The current catalog links a provider-owned guide. Verify that it explicitly supports State Designer before shipping; do not assume a Behavior Designer Pro bridge is source-compatible.

## Related pages

- [Integrations](https://opsive.com/support/documentation/state-designer/integrations/)
- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)
- [Variables](https://opsive.com/support/documentation/state-designer/variables/)
- [Debugging](https://opsive.com/support/documentation/state-designer/debugging/)

---

<a id="page-state-designer-integrations-essential-kit"></a>

# Essential Kit

[View this page online](https://opsive.com/support/documentation/state-designer/integrations/essential-kit/)


Use the [Essential Kit](https://assetstore.unity.com/packages/slug/301752?aid=1100lGdc) integration when a State machine should call supported mobile services such as billing, cloud data, game services, media, notifications, native UI, sharing, web views, or platform utilities.

## Install the integration

1. Download the current **Essential Kit** integration from [Opsive Downloads](https://opsive.com/downloads/).
2. Import `StateDesignerEssentialKit.unitypackage`.
3. Confirm **Native UI Show Alert** appears in the State Palette.

## What the integration adds

- **Service families:** **Address Book**, **App Shortcuts**, **App Updater**, **Billing Services**, **Cloud Services**, **Deep Link Services**, **Game Services**, **Media Services**, **Native UI**, **Network Services**, **Notification Services**, **Rate My App**, **Sharing Services**, **Task Services**, **Utilities**, **Web View**.
- **Event Conditions:** **On Shortcut Clicked**, **On Transaction State Change**, **On Saved Data Change**, **On User Change**, **On Custom Scheme Url Open**, **On Universal Link Open**, **On Auth Status Change**, **On Notification Received**, **On Load Finish**.

This is a large downloaded integration. The installed State Palette is the exhaustive node reference for the Essential Kit version in the project; organize searches by service family rather than scanning one flat list.

## Build a first workflow

1. Configure one Essential Kit service and its platform capabilities first.
2. Use one Action such as **Native UI Show Alert** in a dedicated State.
3. Use its success, error, or event Condition to select the next State.
4. Test on the target device; Editor simulation is not proof that a native service works.

## Related pages

- [Integrations](https://opsive.com/support/documentation/state-designer/integrations/)
- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)
- [Variables](https://opsive.com/support/documentation/state-designer/variables/)
- [Debugging](https://opsive.com/support/documentation/state-designer/debugging/)

---

<a id="page-state-designer-integrations-feel"></a>

# Feel

[View this page online](https://opsive.com/support/documentation/state-designer/integrations/feel/)


Use the [Feel](https://assetstore.unity.com/packages/tools/particles-effects/feel-183370?aid=1100lGdc) integration when entering a State should play one MMFeedback or an MMF Player feedback sequence.

## Install the integration

1. Download the current **Feel** integration from [Opsive Downloads](https://opsive.com/downloads/).
2. Import `StateDesignerFeel.unitypackage`.
3. Confirm **Play Feedbacks** appears in the State Palette.

## What the integration adds

- **Feedback Actions:** **Play Feedback**, **Play Feedbacks**.

## Build a first workflow

1. Create and test one Feel feedback directly.
2. Add **Play Feedback** or **Play Feedbacks** to the entering State.
3. Choose whether completion controls a transition or the feedback runs independently.
4. Re-enter the State and confirm replay/reset behavior is intentional.

## Related pages

- [Integrations](https://opsive.com/support/documentation/state-designer/integrations/)
- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)
- [Variables](https://opsive.com/support/documentation/state-designer/variables/)
- [Debugging](https://opsive.com/support/documentation/state-designer/debugging/)

---

<a id="page-state-designer-integrations-juicy-actions"></a>

# Juicy Actions

[View this page online](https://opsive.com/support/documentation/state-designer/integrations/juicy-actions/)


Use the [Juicy Actions](https://assetstore.unity.com/packages/slug/269711?aid=1100lGdc) integration when a State should run, stop, restart, or inspect an Action Executor, or when a Juicy Action asset should control a State Machine.

## Install the integration

1. Download the current **Juicy Actions** integration from [Opsive Downloads](https://opsive.com/downloads/).
2. Import `StateDesignerJuicyActions.unitypackage`.
3. Confirm **Execute Action Executor** appears in the State Palette.

## What the integration adds

- **State to action:** **Execute Action Executor**, **Wait For Action Executor**, **Stop Action Executor**, **Restart Action Executor**, **Compare Action Executor Status**, **Compare Action Runner Status**, **Is Action Executor Completed**.
- **Clock:** **Clock Get Time**, **Clock Get Time Scale**, **Clock Pause**, **Clock Resume**, **Clock Set Time Scale**, **Clock Wait**.
- **Action assets to State Machine:** **Start State Machine Action**, **Start State Machine Branch Action**, **Stop State Machine Action**, **Pause State Machine Action**, **Resume State Machine Action**, **Restart State Machine Action**, **Get State Machine Status Action**, **Get State Machine Variable Action**, **Set State Machine Variable Action**, **Copy State Machine Variables To Blackboard Action**, **Copy Blackboard To State Machine Variables Action**.

## Build a first workflow

1. Create and verify one Action Executor directly.
2. Run **Execute Action Executor** on State entry.
3. Use **Wait For Action Executor** or a status Condition when completion controls the transition.
4. Copy only the variables both systems need.

## Related pages

- [Integrations](https://opsive.com/support/documentation/state-designer/integrations/)
- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)
- [Variables](https://opsive.com/support/documentation/state-designer/variables/)
- [Debugging](https://opsive.com/support/documentation/state-designer/debugging/)

---

<a id="page-state-designer-integrations-love-hate"></a>

# Love/Hate

[View this page online](https://opsive.com/support/documentation/state-designer/integrations/love-hate/)


Use the Pixel Crushers [Love/Hate](https://assetstore.unity.com/packages/tools/ai/love-hate-33063?aid=1100lGdc) integration when transitions and State Actions depend on factions, affinities, deeds, rumors, emotional state, personality, or relationship traits.

## Install the integration

1. Download the current **Love/Hate** integration from [Opsive Downloads](https://opsive.com/downloads/).
2. Import `StateDesignerLoveHate.unitypackage`.
3. Confirm **Get Affinity** appears in the State Palette.

## What the integration adds

- **Read and check:** **Get Affinity**, **Get Arousal**, **Get Dominance**, **Get Emotional State**, **Get Faction Name**, **Get Happiness**, **Get Personality Trait**, **Get Pleasure**, **Get Relationship Trait**, **Get Temperament**, **Has Ancestor**, **Has Direct Parent**, **Knows Deed**.
- **Change:** **Add Direct Parent**, **Remove Direct Parent**, **Modify Affinity**, **Modify PAD**, **Modify Relationship Trait**, **Report Deed**, **Set Affinity**, **Set Personality Trait**, **Set Relationship Inheritability**, **Set Relationship Trait**, **Share Rumors**.

## Build a first workflow

1. Create two Love/Hate actors and verify their relationship directly.
2. Read affinity into a Shared Variable.
3. Use that value to choose Friendly, Neutral, or Hostile States.
4. Report one deed, then read affinity again and confirm the transition changes.

## Related pages

- [Integrations](https://opsive.com/support/documentation/state-designer/integrations/)
- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)
- [Variables](https://opsive.com/support/documentation/state-designer/variables/)
- [Debugging](https://opsive.com/support/documentation/state-designer/debugging/)

---

<a id="page-state-designer-integrations-playmaker"></a>

# PlayMaker

[View this page online](https://opsive.com/support/documentation/state-designer/integrations/playmaker/)


Use the [PlayMaker](https://assetstore.unity.com/packages/tools/visual-scripting/playmaker-368?aid=1100lGdc) integration when a State Designer graph and a PlayMaker FSM must start, stop, signal, or wait for one another.

## Install the integration

1. Download the current PlayMaker integration from [Opsive Downloads](https://opsive.com/downloads/).
2. Import the downloaded package.
3. Confirm that the expected Actions and Conditions appear and the sample opens.

## What the integration adds

The provider supplies the Actions and Conditions used to hand work between the two products. Inspect the installed selector and provider sample for the exact version-specific list.

## Build a first workflow

1. Build and verify the PlayMaker FSM on its own.
2. Use the current integration package downloaded from Opsive Downloads.
3. Start the FSM from a State and resume State Designer through the matching completion route.
4. Synchronize only the values both graphs need and test cancellation.

## Package and support boundary

Because the provider controls this bridge, the package version, supported platforms, and exact node names can change independently of State Designer. Record the tested combination in the project before upgrading.

- The State Designer online catalog currently routes through the PlayMaker integration family, while local source may be maintained in a separate integration project. Confirm the downloaded package names State Designer and the installed PlayMaker major version.

## Related pages

- [Integrations](https://opsive.com/support/documentation/state-designer/integrations/)
- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)
- [Variables](https://opsive.com/support/documentation/state-designer/variables/)
- [Debugging](https://opsive.com/support/documentation/state-designer/debugging/)

---

<a id="page-state-designer-integrations-quest-machine"></a>

# Quest Machine

[View this page online](https://opsive.com/support/documentation/state-designer/integrations/quest-machine/)


Use the Pixel Crushers [Quest Machine](https://assetstore.unity.com/packages/tools/game-toolkits/quest-machine-39834?aid=1100lGdc) integration when States should create or give quests, inspect and change quest state, update quest UI, or send Quest Machine messages.

## Install the integration

1. Download the current **Quest Machine** integration from [Opsive Downloads](https://opsive.com/downloads/).
2. Import `StateDesignerQuestMachine.unitypackage`.
3. Confirm **Give Quest** appears in the State Palette.

## What the integration adds

- **Quest generation and state:** **Generate Quest**, **Give Quest**, **Get Quest Count**, **Get Quest State**, **Set Quest State**, **Get Quest Node State**, **Set Quest Node State**, **Get Quest Counter Value**, **Set Quest Counter Value**.
- **World and UI:** **Control Spawner**, **Send To Message System**, **Set HUD**, **Set Journal UI**, **Show Quest Alert**, **Start Quest Dialogue**.

## Build a first workflow

1. Verify Quest Machine can give and display one quest directly.
2. Enter a Give Quest State and run **Give Quest**.
3. Use quest State or counter Conditions for later transitions.
4. Confirm the Quest Journal and graph report the same result.

## Related pages

- [Integrations](https://opsive.com/support/documentation/state-designer/integrations/)
- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)
- [Variables](https://opsive.com/support/documentation/state-designer/variables/)
- [Debugging](https://opsive.com/support/documentation/state-designer/debugging/)

---

<a id="page-state-designer-integrations-sensor-toolkit-2"></a>

# Sensor Toolkit 2

[View this page online](https://opsive.com/support/documentation/state-designer/integrations/sensor-toolkit-2/)


Use the [Sensor Toolkit 2](https://assetstore.unity.com/packages/slug/317234?aid=1100lGdc) integration when Conditions should inspect detections, signals, obstruction, seeking, or destination state and Actions should pulse or steer a sensor.

## Install the integration

1. Download the current **Sensor Toolkit 2** integration from [Opsive Downloads](https://opsive.com/downloads/).
2. Import `StateDesignerSensorToolkit.unitypackage`.
3. Confirm **Has Any Detection** appears in the State Palette.

## What the integration adds

- **Actions:** **Pulse**, **Clear**, **Set Seek Target**, **Set Seek Stop**, **Set Strafe Target**.
- **Conditions:** **Has Any Detection**, **Is Detected**, **Is Obstructed**, **Get Detections**, **Get Signal**, **Get Detection Ray Hit**, **Is Seeking**, **Is Destination Reached**.

## Build a first workflow

1. Configure a sensor and verify one target detection directly.
2. Use **Has Any Detection** to enter a Chase State.
3. Store the selected detection and pass it to the seek Action.
4. Return to Patrol when detection fails or the signal becomes invalid.

## Related pages

- [Integrations](https://opsive.com/support/documentation/state-designer/integrations/)
- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)
- [Variables](https://opsive.com/support/documentation/state-designer/variables/)
- [Debugging](https://opsive.com/support/documentation/state-designer/debugging/)

---

<a id="page-state-designer-integrations-simple-waypoint-system"></a>

# Simple Waypoint System

[View this page online](https://opsive.com/support/documentation/state-designer/integrations/simple-waypoint-system/)


Use the [Simple Waypoint System](https://assetstore.unity.com/packages/tools/animation/simple-waypoint-system-2506?aid=1100lGdc) integration when States should select a path or waypoint and start, pause, resume, stop, or retime movement.

## Install the integration

1. Download the current **Simple Waypoint System** integration from [Opsive Downloads](https://opsive.com/downloads/).
2. Import `StateDesignerSimpleWaypointSystem.unitypackage`.
3. Confirm **Set Path** appears in the State Palette.

## What the integration adds

- **Waypoint nodes:** **Set Path**, **Get Waypoint Of Path**, **Set Waypoint Of Path**, **Start Movement**, **Pause Movement**, **Resume Movement**, **Stop Movement**, **Change Speed**, **Update Bezier Path**.

## Build a first workflow

1. Create a path and verify its mover directly.
2. Enter a Patrol State that sets the path and starts movement.
3. Pause and resume from separate States or Events.
4. Transition only after the movement owner reports the intended completion.

## Related pages

- [Integrations](https://opsive.com/support/documentation/state-designer/integrations/)
- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)
- [Variables](https://opsive.com/support/documentation/state-designer/variables/)
- [Debugging](https://opsive.com/support/documentation/state-designer/debugging/)

---

<a id="page-state-designer-integrations-ultimate-character-controller"></a>

# Ultimate Character Controller

[View this page online](https://opsive.com/support/documentation/state-designer/integrations/ultimate-character-controller/)


Use this integration when State Designer chooses an AI or gameplay mode while [Ultimate Character Controller](https://assetstore.unity.com/packages/tools/game-toolkits/ultimate-character-controller-233710?aid=1100lGdc) owns locomotion, abilities, items, health, effects, and animation.

## Install the integration

1. Download the current **Ultimate Character Controller** integration from [Opsive Downloads](https://opsive.com/downloads/).
2. Import `UltimateCharacterControllerStateDesigner.unitypackage`.
3. Confirm **Start Stop Ability** appears in the State Palette.

## What the integration adds

- **Abilities and effects:** **Start Stop Ability**, **Is Ability Active**, **Start Stop Effect**, **Is Effect Active**.
- **Items and aim:** **Set Aim Target**, **Start Stop Use**, **Reload**, **Start Equip Unequip**, **Start Item Set Ability**, **Get Item Identifier Amount**.
- **Health and state:** **Damage**, **Heal**, **Is Alive**, **Has Taken Damage**, **Get Attribute Value**, **Set State**, **Execute Event**.

## Build a first workflow

1. Build the character as an Ultimate Character Controller AI Agent and verify one ability without State Designer.
2. Use States such as Patrol, Chase, and Attack for durable modes.
3. In Attack, set the aim target and start the required Aim or Use ability.
4. On State exit, stop abilities that should not remain active and clear temporary targets.
5. Use Ultimate Character Controller checks as transition Conditions rather than reading the Animator directly.

## Related pages

- [Integrations](https://opsive.com/support/documentation/state-designer/integrations/)
- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)
- [Variables](https://opsive.com/support/documentation/state-designer/variables/)
- [Debugging](https://opsive.com/support/documentation/state-designer/debugging/)

---

<a id="page-state-designer-integrations-ultimate-inventory-system"></a>

# Ultimate Inventory System

[View this page online](https://opsive.com/support/documentation/state-designer/integrations/ultimate-inventory-system/)


Use this integration when a State or transition must inspect or change a released [Ultimate Inventory System](https://assetstore.unity.com/packages/tools/game-toolkits/ultimate-inventory-system-166053?aid=1100lGdc) Version 1 Inventory, Currency amount, panel, interaction, or save.

## Install the integration

1. Download the current **Ultimate Inventory System** integration from [Opsive Downloads](https://opsive.com/downloads/).
2. Import `UltimateInventorySystemStateDesigner.unitypackage`.
3. Confirm **Has Item With Definition** appears in the State Palette.

## What the integration adds

- **Items:** **Add Item**, **Remove Item**, **Has Item With Definition**, **Has Item With Category**, **Compare Item Amount**, **Drop Item From Inventory**, **Exchange Item Between Inventories**.
- **Currency:** **Add Currency**, **Remove Currency**, **Has Currency**, **Compare Currency**.
- **Actions and UI:** **Use Item From Inventory**, **Use Item Object**, **Interact**, **Open Close Panel**.
- **Persistence:** **Save**, **Load**, **Delete Save**.

## Build a first workflow

1. Put the State Machine on the Inventory GameObject for the first test.
2. Use **Has Item With Definition** as the transition into a Use Potion State.
3. Run **Use Item From Inventory** as that State's Action.
4. Return to the prior State when the action completes or fails.
5. Inspect the Inventory amount after the transition.

## Related pages

- [Integrations](https://opsive.com/support/documentation/state-designer/integrations/)
- [Actions](https://opsive.com/support/documentation/state-designer/concepts/actions/)
- [Variables](https://opsive.com/support/documentation/state-designer/variables/)
- [Debugging](https://opsive.com/support/documentation/state-designer/debugging/)
