Skip to content

WBP Anim State Machine User Guide

This guide walks through using the WbpAnimStateMachine module as a widget author.

The goal is simple:

  • create a widget with named animations
  • define states and transitions in a data asset
  • create the machine in the widget
  • drive transitions from Blueprint, input, tracks, or Sequencer
  • debug the result in PIE

The same workflow works for:

  • buttons
  • panels and modals
  • toasts
  • tabs
  • loading screens
  • menu screens
  • nested composite widgets

You need:

  • a widget blueprint
  • one or more UMG animations in that widget
  • the WbpAnimStateMachine module enabled

Best practice:

  • keep state names and animation names aligned when possible

Example:

  • state Hover
  • animation Hover

The workflow has three pieces:

  1. Widget blueprint
  • contains the real UMG animations
  1. Definition asset
  • describes states, transitions, rules, notes, graph layout, and input bindings
  1. Runtime machine
  • created inside the widget and asked to move between states

In the Content Browser:

  1. Right-click
  2. Choose Miscellaneous
  3. Choose Data Asset
  4. Select WbpAnimStateMachineDefinition
  5. Name it something like DA_ButtonAnimStateMachine

The dedicated asset editor gives you:

  • a graph tab
  • a details tab
  • a debugger tab

Set OwnerWidgetClass to the widget blueprint that will use this definition.

This enables:

  • animation dropdowns
  • entry/exit/condition function dropdowns
  • better validation

Set PresetToApply and click Apply Preset.

Good starting presets:

  • Button
  • ToggleButton
  • Panel
  • Toast
  • Tab
  • LoadingScreen
  • Carousel

This fills in:

  • InitialState
  • States
  • Transitions

The state machine does not create animations. Your widget blueprint still owns them.

If your definition includes:

  • Idle
  • Hover
  • Pressed
  • Focused
  • Disabled

then the widget should contain matching animations or intentionally remapped AnimationName values.

Each state gives you the behavior for one named UI mode.

Common settings:

  • StateName
  • AnimationName
  • PlayMode
  • PlaybackRate
  • StartTime
  • bRestoreState
  • ReEnterPolicy
  • InterruptPriority
  • Group
  • StateTags
  • DesignerNotes
  • CurveAtlasDuration
  • CurveAtlasBindings

ReEnterPolicy controls what happens when the machine is already in the target state:

  • Ignore
  • RestartAnimation
  • Fire Events

You can move to another state automatically after a delay:

  • AutoTransitionDelay
  • AutoTransitionState

Common use:

  • Visible for 3 seconds
  • then move to Dismiss

States can call widget functions on enter and exit:

  • EntryFunctionName
  • ExitFunctionName

Use this for:

  • playing sounds
  • toggling visibility
  • starting helper effects
  • updating related widget state

EditorNodeColor is editor-only and lets you color important states in the graph without affecting runtime behavior.

Use it to make:

  • danger/error states obvious
  • accessibility states grouped visually
  • parent vs child states easier to scan

If a state only needs simple timed property motion, you can use a Curve Atlas sequence instead of authoring a full UMG animation timeline. Set CurveAtlasDuration, then add CurveAtlasBindings for the widgets and properties you want to drive.

Each binding samples a UCurveLinearColor row over the state’s normalized playback time. RGBA values can drive opacity, render transform values, common widget tint/color properties, or a visibility threshold. Leave WidgetName empty to target the owning widget itself.

These sequences use the state’s PlayMode and PlaybackRate. PlayOnce and Reverse curve-only states can still advance through OnAnimationFinished transitions when the sequence completes. Loop and PingPong keep running until the state changes.

Transitions describe allowed moves between states.

These happen only when you explicitly call GoToState.

Example:

  • Idle -> Hover
  • Hover -> Pressed

These happen when the current animation finishes.

Example:

  • Intro -> Idle
  • Pressed -> Hover
  • Outro -> Hidden

If FromState is None, the transition can match from any current state.

Use this for:

  • Any -> Disabled
  • Any -> Focused

Useful fields:

  • Trigger
  • BlendTime
  • ConditionFunctionName
  • Rules
  • RuleMatchMode
  • TransitionTag
  • DesignerNotes
  • bEnableBreakpoint

TransitionGuard exists for C++ integrations only. If you are working in Blueprint, use ConditionFunctionName or built-in transition Rules for guard logic.

Rules let you gate transitions without needing a custom widget function every time.

Supported rule sources include:

  • blackboard float
  • blackboard bool
  • blackboard name
  • blackboard int
  • blackboard string
  • time in state
  • animation progress
  • current state
  • previous state

Good uses:

  • only allow dismiss after CanDismiss == true
  • only allow next state after progress > 0.8
  • only allow exit from one prior state

The blackboard is a lightweight per-machine data store.

Supported types:

  • float
  • bool
  • FName
  • int32
  • FString
  • UObject*

Typical keys:

  • HasUnread
  • SelectedTab
  • CanDismiss
  • InputSource
  • CurrentPage

From Blueprint you can use:

  • SetBlackboardFloat
  • SetBlackboardBool
  • SetBlackboardName
  • SetBlackboardInt
  • SetBlackboardString
  • SetBlackboardObject

and the matching getters.

Creating the Runtime Machine in Your Widget

Section titled “Creating the Runtime Machine in Your Widget”

Typical Blueprint path:

  1. Add a variable of type WbpAnimStateMachine
  2. On widget construct or initialize:
  3. call CreateAndInitializeStateMachine
  4. store the result

Typical C++ path:

StateMachine = UWbpAnimStateMachine::CreateStateMachine(this, DefinitionAsset);

Most common nodes:

  • Go To WBP State
  • Go To WBP State And Wait
  • GoToState
  • GoBack
  • CanTransitionTo
  • GetAvailableTransitions
  • GetCurrentState
  • IsInState

In editor builds, the best default node is Go To WBP State.

Why it is better than a plain GoToState call:

  • it still performs a normal runtime transition
  • but it adds an optional State Definition pin
  • when a definition is available, the State pin becomes a dropdown of valid authored state names
  • the custom nodes appear under UI Foundry|State Machine in the Blueprint action menu

Best practice:

  1. Create your machine from a definition asset
  2. Use Go To WBP State for most direct transitions
  3. Set State Definition explicitly when the node cannot infer it from the machine creation path

The editor pin factory also upgrades standard Blueprint-library GoToState and GoToStateAndWait nodes when the definition can be inferred, but the custom node is the clearest workflow for designers and technical artists.

There is now also a matching Go To WBP State And Wait custom node, which keeps the same authored-state dropdown while using the latent wait behavior.

Use GoToStateAndWait when you want a clean sequential Blueprint flow.

Example pattern:

  1. GoToStateAndWait(Intro)
  2. continue only after Intro has actually been entered
  3. GoToState(Idle)

This is much cleaner than wiring temporary delegate listeners for simple scripted flows.

If your widget already created a machine and another Blueprint needs to find it later, use:

  • FindMachineByDefinition(Widget, Definition)

This is useful when:

  • UI controller logic does not already store the machine pointer
  • game code wants to drive a specific widget machine indirectly

There are two save paths:

  • SaveState / RestoreState

  • stores only the current state name

  • SaveMachineSnapshot / RestoreMachineSnapshot

  • stores current state plus the full blackboard

Use full snapshots when the UI has real authored context, not just a single active state.

Example:

  • a crafting panel with tabs, sort choice, selection, and mode flags

If one widget needs multiple independent animation layers, use a UWbpAnimStateMachineGroup.

Good examples:

  • base panel flow on one track
  • hover/focus feedback on a second track
  • attention pulse on a third track

Blueprint helpers:

  • CreateStateMachineGroup
  • AddTrack
  • GetTrack
  • GetTrackNames
  • GoToStateOnTrack
  • TickGroup
  • StopAllTracks

A state can host a nested child definition through:

  • SubMachineDefinition
  • SubMachineMode

This is ideal when one parent state has its own internal behavior.

Example:

  • parent state Searching
  • child machine states Pulse, Spin, Found

Useful modes:

  • EnterAndRunConcurrently
  • EnterAndPauseParent
  • EnterAndWaitForExit

You can author input-driven transitions directly on the definition using InputBindings.

Each input binding gives you:

  • InputAction
  • TriggerEvent
  • TargetState
  • bForce
  • CallerPriority

At runtime the machine looks for an UEnhancedInputComponent on the owning player’s controller and binds those actions automatically during Initialize().

States can also manage mapping contexts directly:

  • EntryInputContext
  • EntryInputContextPriority
  • ExitInputContext

The easiest pattern is:

  1. Set EntryInputContext = IMC_WidgetFocus
  2. Set ExitInputContext = IMC_WidgetFocus

That makes the state add the focus mapping context when it becomes active and remove it when the state ends.

Good uses:

  • confirm and cancel on controller
  • gamepad menu states
  • tab navigation
  • focused or modal states that should temporarily swap input behavior

You can also add bindings manually in Blueprint with:

  • AddInputBinding

If your widget should react to focus without custom Blueprint glue, enable focus-aware transitions on the definition:

  • enable bEnableFocusAwareTransitions
  • set FocusGainedState
  • set FocusLostState

Then, while MachineTick is running, the machine will watch the widget’s focus state and request those transitions automatically.

This is a good fit for:

  • gamepad-focus button widgets
  • accessibility-focused menu items
  • widgets that should visually elevate when they become the active focus target

Starter example:

  • examples/WbpAnimStateMachine/EX_FocusAwareButton.json

If your widget stores a UObject view-model, you can bind reflected fields directly into the state machine blackboard.

Definition fields:

  • WidgetViewModelProperty
  • ViewModelField
  • BlackboardKey
  • Direction

What this gives you:

  • transition rules can react to view-model values without manual setter glue
  • blackboard-driven flows can push values back into the view-model when desired
  • the widget and machine stay synchronized while MachineTick runs

Reference recipe:

  • examples/WbpAnimStateMachine/EX_ViewModelBoundPanel.md

If your project uses the CommonUI plugin, UWbpAnimCommonActivatableMixin lets you drive state machine transitions from the CommonUI activation lifecycle without a hard plugin dependency.

  1. In NativeConstruct or Construct, call BindActivationEvents(Self, StateMachine, "Active", "Inactive").
  2. In the widget’s OnWidgetActivated event, call NotifyActivated(Self).
  3. In OnWidgetDeactivated, call NotifyDeactivated(Self).

C++ setup (on a UCommonActivatableWidget subclass)

Section titled “C++ setup (on a UCommonActivatableWidget subclass)”
// NativeConstruct
UWbpAnimCommonActivatableMixin::BindActivationEvents(this, MyMachine, TEXT("Active"), TEXT("Inactive"));
// NativeOnActivated
Super::NativeOnActivated();
UWbpAnimCommonActivatableMixin::NotifyActivated(this);
// NativeOnDeactivated
Super::NativeOnDeactivated();
UWbpAnimCommonActivatableMixin::NotifyDeactivated(this);
  • If the widget is not a UCommonActivatableWidget subclass, BindActivationEvents returns false and logs a warning. Nothing crashes.
  • Stale entries for destroyed widgets are cleaned up automatically.
  • To stop bridging, call UnbindActivationEvents(Self).

If your project uses Gameplay Ability System, you can route ability event tags directly into state machine transitions without writing manual GoToState calls in every ability.

In the definition asset: Add entries to the GAS Events array. Each entry has:

FieldPurpose
Event TagThe FGameplayTag that triggers this binding
Target StateState to enter when the tag fires
ForceIf checked, requests GoToState in force mode and bypasses the transition table
Caller PriorityPriority used when Force is checked; it must meet or exceed the current state’s InterruptPriority

Inline (C++ only): Call AddGasEventBinding(Tag, StateName) before Initialize().

The machine does not subscribe to UAbilitySystemComponent automatically — you forward events with one call:

Blueprint:

  1. Subscribe to whatever GAS event you care about (e.g. from an UGameplayAbility or a tag listener)
  2. Get your state machine reference
  3. Call Handle Gameplay Event and pass the tag

C++:

// Example: inside your widget's NativeConstruct
UAbilitySystemComponent* ASC = GetOwningPlayerState<AMyPlayerState>()->GetAbilitySystemComponent();
ASC->AddGameplayEventTagContainerDelegate(
FGameplayTagContainer(MyTag),
FGameplayEventTagMulticastDelegate::FDelegate::CreateWeakLambda(this,
[this](FGameplayTag Tag, const FGameplayEventData*)
{
if (StateMachine) StateMachine->HandleGameplayEvent(Tag);
}));

HandleGameplayEvent uses FGameplayTag::MatchesTag. A binding for Gameplay.Damage will fire when Gameplay.Damage.Fire or Gameplay.Damage.Ice comes in. Use an exact tag in the binding to restrict to a single event type.

  • No hard dependency on the GameplayAbilities plugin is added. FGameplayTag is from GameplayTags, which is already a module dependency.
  • HandleGameplayEvent returns an int32 — the number of bindings that successfully triggered a GoToState. Zero means no match or the machine is not initialized.
  • If multiple bindings match the same incoming tag, they are evaluated in declaration order. Each call runs from the state left by the previous successful binding, so later bindings can succeed or be blocked by the transition table from that new state.
  • Force bypasses the transition table, but not interrupt protection. If the current state has a higher InterruptPriority than the binding’s CallerPriority, the forced transition is rejected.
  • Validation checks that all TargetState values exist and all EventTag values are valid. Errors appear when you press Validate State Machine in the definition asset.

The module includes a custom Sequencer track path for discrete state transitions.

Current authoring flow:

  1. Bind your widget object in Sequencer
  2. Add a WBP Anim State track
  3. Add sections for target states
  4. Configure:
  • TargetState
  • machine property name
  • or machine-group property plus track name
  • optional force/priority

Blueprint/editor-script helpers also exist:

  • AddSequencerStateTrack
  • AddSequencerStateSection

This is ideal for:

  • menu reveals
  • title-card sequences
  • scripted onboarding or splash flows

The graph is the main authoring surface for most users.

You can:

  • drag states around
  • pan and zoom
  • search states
  • use the minimap
  • frame all
  • select multiple nodes
  • align and distribute nodes
  • duplicate or copy/paste states
  • use group boxes
  • add sticky notes
  • add standard graph comments
  • delete selected states or comments with Delete or Backspace
  • auto-arrange the graph with Compact, Flow, Wide, or Selected layout modes

You can drag from any node edge to another state to create a transition.

This is much more discoverable than an invisible single-side hotspot and is the intended everyday workflow.

The default native Graph tab keeps nodes visually stable and does not rely on collapsing nodes for day-to-day readability.

For large graphs, prefer auto-layout, comments, group boxes, search, frame-selection, and the minimap. The older custom Slate graph has been removed, so the native graph is the single production authoring surface.

Use the graph toolbar’s layout actions to quickly reshape a state machine:

  • Compact keeps short state flows close together for editing.
  • Flow emphasizes the initial state and primary transition direction.
  • Wide gives dense graphs extra horizontal breathing room.
  • Selected lays out only the selected states and preserves the rest of the graph.

Auto-layout uses the initial state as the preferred starting point when one is set. Special nodes such as Entry and Any State are positioned as helpers rather than treated as normal runtime states.

Press G to toggle grid snap.

When enabled:

  • node movement snaps on release
  • the graph is easier to keep tidy

The graph supports:

  • transition context menus
  • selected transition inspector
  • keyboard shortcuts for selected transitions
  • breakpoint toggles

The Graph tab uses Unreal’s graph framework (UEdGraph / SGraphEditor) for state-machine authoring. It replaces the older custom canvas.

The graph is editor-only and synchronized from the same definition asset. It is not a second runtime format and does not add separate serialized state-machine data.

Use the default graph for:

  • native selection and context menus
  • pin and edge authoring
  • graph rewiring that writes back to the definition
  • native connector routing and arrow rendering

The connector drawing chooses anchors along the surrounding node edge, distributes dense endpoints, renders bidirectional links as readable parallel lanes, and rotates arrowheads to match the incoming connector direction.

The native graph also supports standard graph comments, Backspace/Delete deletion, transaction-aware edits, and graph-driven state/transition creation.

For production authoring, use Graph as the canonical visual editor for the definition.

Use group boxes to organize areas of the graph.

They support:

  • dragging
  • resizing
  • renaming
  • fit-to-contained-states
  • color presets

Use sticky notes for freeform reminders such as:

  • TODO items
  • content assumptions
  • mobile-only notes
  • accessibility notes

Open the definition asset and switch to the Debugger tab while PIE is running.

What you get:

  • live machine instance list
  • current and previous state
  • time in state
  • animation progress
  • transition summary
  • blocked reason
  • blackboard watch
  • transition log
  • runtime stats
  • state timeline

You can set:

  • transition breakpoints
  • condition breakpoints

These are useful when a machine only misbehaves under very specific game state.

If several widgets use the same definition, the debugger can switch between instances and compare them.

The tester panel lets you validate a machine at authoring time.

Use it for:

  • stepping through a transition script
  • seeing visited-state coverage
  • fuzz testing random walks

This is especially helpful before the widget itself is fully wired into gameplay.

The tester simulates state-machine transition reachability; it does not visually preview the owning Widget Blueprint’s UMG animation timeline. It also does not execute Blueprint condition functions, transition rule arrays, or InterruptPriority checks for forced transitions. Use PIE, the Widget Blueprint animation timeline, Sequencer, or the owning widget preview path when you need runtime-accurate behavior or rendered animation review.

Test sequences can be saved as UWbpAnimTestSequenceAsset data assets and reloaded later.

To save:

  1. Build a sequence in the tester panel - set a start state and add steps.
  2. Enter a content path in the State Machine Test Asset box (e.g. /Game/Tests/DA_ButtonSequence), or use the asset picker beside it.
  3. Press Save.

To load:

  1. Enter the content path of an existing asset in the State Machine Test Asset box, or choose one with the picker.
  2. Press Load - the steps are restored into the tester.

The tester shows an inline status message for invalid paths, failed saves, failed loads, and successful save/load operations, so you do not need to rely only on the Output Log.

The asset stores:

  • InitialState
  • each step’s TargetState, bForce, and an optional Comment
  • a multiline Description field for documentation

You can also create assets directly in the Content Browser (Miscellaneous -> Data Asset -> WbpAnimTestSequenceAsset) and hand-author them as regression sequences or acceptance tests.

The definition asset exposes:

  • Export State Diagram (SVG)
  • Export Definition (JSON)
  • Import Definition (JSON)
  • Generate State Enum Header

Output location:

  • Saved/WbpAnimStateMachineExports

Generated enum header location:

  • Saved/WbpAnimStateMachineExports/GeneratedHeaders

Important note:

  • the generated enum header is not automatically compiled into your project
  • copy it into your game Source tree if you want to use it directly in C++

Validation catches common authoring mistakes such as:

  • duplicate state names
  • invalid initial state
  • bad animation names
  • bad function references
  • invalid transition endpoints
  • invalid input binding targets
  • unreachable states

The definition editor surfaces live validation output while authoring, so you do not have to rely only on a manual validation button. The older editor-module-only details hint has been removed; the native definition editor and the runtime/editor module’s details customization are now the authoritative authoring surfaces.

  • Create machine from a Button preset
  • call GoToState(Hover) on pointer enter
  • call GoToState(Pressed) on pointer down
  • let Pressed -> Hover finish automatically
  • drive gamepad focus through input bindings or explicit state changes
  • Hidden -> Intro -> Idle -> Outro -> Hidden
  • use OnAnimationFinished transitions for Intro and Outro
  • use GoToStateAndWait when you need to continue a scripted flow only after Intro
  • Spawn -> Visible -> Dismiss
  • use an auto-transition on Visible
  • use a full snapshot if the toast stores mode or content state in the blackboard
  • parent machine handles section-level flow
  • child machine handles local detail motion
  • Keep state names simple and stable
  • Use presets for first pass authoring
  • Set OwnerWidgetClass immediately
  • Prefer built-in rules before writing lots of widget condition functions
  • Use tracks instead of giant combined state explosion
  • Use notes and group boxes to keep bigger graphs readable
  • Add breakpoints early when a flow becomes hard to reason about
  • Use snapshots when UI state carries data, not just animation mode
  • Save regression sequences as UWbpAnimTestSequenceAsset so they can be replayed after refactors
  • Use UWbpAnimCommonActivatableMixin for CommonUI widgets rather than duplicating GoToState calls in every widget subclass