Unit Action Graph
Categories:
Under Construction
The Unit Action Graph editor is functional, but runtime integration with the Unit movement system is not yet complete. You can author graphs and work with the editor today; full in-game execution arrives in a future release.The Unit Action Graph is a visual editor for authoring character behavioral logic as a Hierarchical Finite State Machine (HFSM). Where the Movement system handles how a character moves — velocity, surface contact, physics — the Unit Action Graph defines what the character is doing: idle, walking, attacking, interacting, and when to switch between those states.
Behavior is authored in a .unitaction file as a set of parallel layers, each an independent state machine that evaluates simultaneously. A typical setup has a Movement layer, an Action layer, and a Rotation layer all running at once.
For component properties and C++ extension, see the Framework API reference.
Contents
- Opening the Editor
- The Editor Layout
- Working with Layers
- States and Transitions
- Transition Conditions
- Using Variables
- Parallel Layers in Practice
- Quick Reference
- Glossary
- See Also
Opening the Editor
From the O3DE Editor menu bar: GS Tools > Unit Action Graph Editor.
- File > New — Creates a new
.unitactioncontainer file - File > Open — Opens an existing
.unitactionfile
All layers for one character type live in a single file. Save with File > Save (Ctrl+S).
The Editor Layout
The editor has two main areas:
Layer Sidebar (left dock) — Lists all layers in the file. Use the toolbar buttons to add, remove, rename, or duplicate layers. Click a layer name to open it as a graph tab.
Graph Canvas (center) — The state machine for the selected layer. States are nodes; transitions are arrows drawn from the edge of one state to the edge of another.
Inspector (right dock) — Shows properties for the selected state or transition.
Variable Panel (dock) — Declare named variables shared across all layers.
Working with Layers
Adding a Layer
- Click Add in the Layer Sidebar
- Name the layer (e.g.,
"Movement","Action","Rotation") - Set its Priority in the Layer Details panel — higher values override lower ones when resolving conflicts
Each new layer starts with a single Entry node and a blank canvas.
Layer Priority
When layers share variables to communicate, priority determines which layer’s state outputs take precedence. A higher-priority Action layer can suppress a lower-priority Movement layer’s output when a blocking action is playing.
States and Transitions
Adding States
Drag a State node from the Node Palette onto the canvas. Name it to match the behavior it represents: Idle, Walk, Run, Attack.
The Entry Node
Every layer has exactly one Entry node — auto-spawned and non-deletable. Draw a transition from the Entry node to whichever state the machine should start in.
Drawing Transitions
Click and drag from the edge of one state to the edge of another. A transition arrow appears between them.
- Connections go from the perimeter of one state to the perimeter of the target
- Multiple transitions from the same source are allowed
- When several transitions are valid simultaneously, the one with the highest priority fires
Inspecting a Transition
Click a transition arrow to select it. The Inspector shows:
| Field | Description |
|---|---|
| Priority | Integer. Higher values fire first when multiple transitions are valid. |
| Conditions | List of conditions. All must pass for the transition to fire. Add via the type picker dropdown. |
Inspecting a State
Click a state node to select it. The Inspector shows the node’s properties and a Transition Summary below — a list of every outgoing transition with priority and condition count, and a Select button to jump to that connection’s inspector.
Compound States
A Compound State node contains its own nested state machine. Use them for behaviors with internal sub-states — for example, a Jump state that internally tracks Rising, Apex, and Falling. The nested graph starts from its own Entry node when the compound state is entered.
Transition Conditions
Conditions gate when a transition fires. Add them in the Inspector when a transition is selected — click the type picker dropdown and choose a condition type. All conditions in the list must pass for the transition to be valid.
Built-in Conditions
| Condition | When It Fires |
|---|---|
| VariableCompareCondition | A named variable satisfies a comparison (==, !=, <, >, <=, >=) against a set value |
| TimeElapsedCondition | The character has been in the current state for at least N seconds |
| VariableTrueCondition | A named boolean variable is true |
Condition-Free Transitions
A transition with no conditions fires as soon as the current state’s tick completes. Use a condition-free transition from an animation state to its follow-up state when you want an unconditional sequence.
Using Variables
Variables are named values declared in the Variable Panel dock. They are shared across all layers in the file — any layer can read or write them.
Common uses:
"speed"(Float) — set by the input system each frame, read by movement transitions"isGrounded"(Bool) — set by the grounder, read by jump/fall transitions"isAttacking"(Bool) — set by the Action layer, read by Movement to restrict options"stateTime"(Float) — the auto-variable__stateTimetracks how long the current state has been active
Declaring a Variable
- Open the Variable Panel
- Click Add
- Set the name and type (Bool, Int, Float, String, etc.)
- Optionally set a default value
Variables can also be set from gameplay code once runtime integration is available.
Parallel Layers in Practice
All layers evaluate simultaneously on every tick. Because they share variables, they can communicate cleanly:
Example: Attack while running
Movement layer (priority 0):
Idle → Walk (condition: speed > 0.1)
Walk → Run (condition: speed > 4.0)
Action layer (priority 1):
None → Attack (condition: attackInput == true)
Attack → None (condition: TimeElapsed >= 0.8)
Both layers run at the same time. The character walks or runs independently of whether an attack is playing. The Action layer sets isAttacking = true on enter and false on exit — the Movement layer can read this variable to restrict sprinting during attacks if needed.
Layer priority determines which layer’s output the movement system uses when both claim the same channel. Higher priority wins.
Quick Reference
| Task | How |
|---|---|
| Open editor | GS Tools > Unit Action Graph Editor |
| Create a new file | File > New |
| Add a layer | Layer Sidebar > Add |
| Add a state | Drag State node from the palette |
| Draw a transition | Drag from the edge of one state to the edge of another |
| Set transition priority | Select the transition arrow → Inspector → Priority field |
| Add a condition | Select the transition arrow → Inspector → Conditions → type picker |
| Declare a variable | Variable Panel → Add |
| Inspect a connection | Click the transition arrow |
| Jump to a transition from a state | Select state → Transition Summary → Select button |
Glossary
| Term | Meaning |
|---|---|
| Layer | One independent state machine within a .unitaction file, evaluated in parallel with all others |
| State | A node representing one behavior the character can be in |
| Entry Node | The auto-spawned marker that designates the initial state of a layer |
| Compound State | A state that contains its own nested state machine sub-graph |
| Transition | A directed connection between states, with priority and optional conditions |
| Condition | A rule that must be satisfied for a transition to fire |
| Priority | The tie-breaker when multiple transitions from the same state are simultaneously valid |
__stateTime | Auto-variable tracking how long the character has been in the current state (seconds) |
For full definitions, see the Glossary.
See Also
For the full API, node types, and C++ extension guide:
For related systems:
- The Basics: Movement — Locomotion physics that the Unit Action Graph will drive
- The Basics: Units — Unit entity setup and possession
- gs_graphcanvas Framework — The underlying graph editor framework
Get GS_Unit
GS_Unit — Explore this gem on the product page and add it to your project.