WBP Anim State Machine Walkthroughs
WBP Anim State Machine - Hands-On Walkthroughs
Section titled “WBP Anim State Machine - Hands-On Walkthroughs”This document walks through six complete, real-world UI setups from first principles.
It is written for people who are new to Widget Blueprints or Unreal Blueprints in general. Every step, including things experienced developers would consider obvious, is spelled out explicitly.
Before You Start: Key Concepts
Section titled “Before You Start: Key Concepts”If you have used Widget Blueprints before, skip ahead to Walkthrough 1. If not, read this section first.
What is a Widget Blueprint?
Section titled “What is a Widget Blueprint?”A Widget Blueprint (WBP) is a type of Unreal asset that describes a piece of on-screen UI. It is made up of two parts:
- The Designer tab - a visual canvas where you place UI elements such as images, text, buttons, and panels by dragging and dropping them.
- The Graph tab - a Blueprint scripting area where you write the logic that controls those elements.
A Widget Blueprint is not displayed on screen by itself. You create an instance of it at runtime, usually by calling Create Widget from another Blueprint (such as a HUD or a Player Controller), and then add it to the viewport.
What is a UMG Animation?
Section titled “What is a UMG Animation?”Inside a Widget Blueprint, the Animations panel (usually at the bottom left of the Designer tab) lets you create named animations. Each animation can move, fade, scale, or colour any element in the widget over time, using keyframes on a mini timeline.
These animations are the building blocks the state machine plays back. When the machine enters a state called Hover, it looks up a widget animation also called Hover and plays it.
You do not need to wire any Blueprint nodes to play an animation. The machine handles that automatically once the state and animation names match.
What is the State Machine doing?
Section titled “What is the State Machine doing?”Think of the state machine as a traffic controller for your widget’s animations. Instead of writing Play Animation Hover in twenty different places across your Blueprint graph, you define:
- States - the named modes the widget can be in (
Idle,Hover,Pressed) - Transitions - the allowed moves between those states (
Idle -> Hover,Hover -> Pressed) - Rules - optional conditions that must be true before a transition fires
Then, from Blueprint, you only ever say: “go to Hover”. The machine decides whether that is allowed, fires the correct animation, and keeps a record of where it came from.
Where is the state described?
Section titled “Where is the state described?”The behavior is described in a Definition asset - a data asset you create in the Content Browser that stores states, transitions, and rules. It is separate from the widget blueprint. One definition asset can be reused by multiple different widget blueprints.
Three things you always need
Section titled “Three things you always need”- A Widget Blueprint containing your UMG animations.
- A Definition asset (
WbpAnimStateMachineDefinition) describing the states and transitions. - A few Blueprint nodes inside the widget to create the machine and ask it to move between states.
Timeline animation vs Curve Atlas sequence
Section titled “Timeline animation vs Curve Atlas sequence”Most walkthroughs use normal UMG animations because that is the common Widget Blueprint workflow. A state can also drive a lightweight timed property sequence from CurveAtlasDuration and CurveAtlasBindings.
Use a UMG animation when you want to edit keys directly in the Widget Blueprint timeline. Use a Curve Atlas sequence when a state only needs reusable curve-driven property motion such as opacity, transform, tint, or visibility thresholding. Both approaches still live inside the same state machine and can use OnAnimationFinished transitions when playback is finite.
Walkthrough 1: Animated Button
Section titled “Walkthrough 1: Animated Button”Goal: A button widget that smoothly transitions between Idle, Hover, and Pressed states in response to mouse input.
Time estimate: 20-30 minutes for a first attempt.
What you will build
Section titled “What you will build”A Widget Blueprint with three UMG animations - Idle, Hover, and Pressed - driven by a state machine. Hovering over the widget plays the hover animation. Clicking plays the pressed animation. Moving the mouse away returns to idle.
Step 1 - Create the Widget Blueprint
Section titled “Step 1 - Create the Widget Blueprint”- In the Content Browser, right-click in a folder such as
Content/UI/Widgets. - Choose User Interface -> Widget Blueprint.
- Name it
WBP_Button. - Double-click it to open the Widget Blueprint editor.
The editor opens to the Designer tab by default.
Step 2 - Add a visual element to the widget
Section titled “Step 2 - Add a visual element to the widget”For this walkthrough you just need something visible. A simple image or a coloured box is enough.
- In the Palette panel on the left, find Image.
- Drag an
Imagewidget onto the canvas. - In the Details panel on the right, set its size - for example, 400 x 100 - and give it a background colour under Brush -> Tint. Any colour is fine.
- Name it something like
BGin the Hierarchy panel.
Step 3 - Create three UMG animations
Section titled “Step 3 - Create three UMG animations”Animations live in the Animations panel at the bottom left. If you do not see it, make sure you are on the Designer tab, not the Graph tab.
Create the Idle animation
Section titled “Create the Idle animation”- Click + Animation in the Animations panel.
- Name it exactly
Idle(case matters - the state machine matches by name). - The animation timeline opens at the bottom.
- Select the
BGimage in the Hierarchy. - Click + Track in the timeline header and choose
BG. - Add a Render Opacity or Render Transform -> Scale track.
- Set keyframes so the button looks like its default resting state - for example, opacity 1.0 at time 0 and time 0.5 seconds. A flat, looping animation is fine for idle.
Create the Hover animation
Section titled “Create the Hover animation”- Click + Animation again.
- Name it exactly
Hover. - Select
BG, add a track, and keyframe a subtle scale or brightness change - for example, scale from1.0to1.05between 0 and 0.15 seconds. - This animation will play once when the mouse enters. Choose Play Once as its play mode in the state configuration later.
Create the Pressed animation
Section titled “Create the Pressed animation”- Click + Animation again.
- Name it exactly
Pressed. - Keyframe a quick scale-down pulse - for example, scale from
1.0to0.95at 0.05 s, then back to1.0at 0.15 s.
Tip: The names
Idle,Hover, andPressedare case-sensitive. The state machine will look for an animation with the exact same name as the state. If the animation is namedhover(lowercase h) but the state isHover, the animation will not play - but the machine will still work correctly, it simply will not find the animation.
Step 4 - Create the Definition Asset
Section titled “Step 4 - Create the Definition Asset”- In the Content Browser, right-click in a folder such as
Content/UI/StateMachines. - Choose Miscellaneous -> Data Asset.
- In the picker that opens, type
WbpAnimStateMachineDefinitionand select it. - Name the asset
DA_Button. - Double-click it to open the asset editor.
The editor opens with the native Graph tab plus supporting tabs for Details, Debugger, Test, and Diff.
Step 5 - Set OwnerWidgetClass
Section titled “Step 5 - Set OwnerWidgetClass”This is the single most important setup step. It tells the editor which widget blueprint owns the animations and functions you want to reference.
- Click the Details tab.
- Find the Owner Widget Class property.
- Click the dropdown and search for
WBP_Button. Select it.
Once this is set, animation dropdowns and function dropdowns throughout the editor will populate from your real widget.
Step 6 - Apply the Button preset
Section titled “Step 6 - Apply the Button preset”- In the Details tab, find Preset To Apply.
- Click the dropdown and select Button.
- Click Apply Preset.
This fills in a sensible starting set of states and transitions. Switch to the Graph tab - you should now see state nodes arranged on the canvas:
IdleHoverPressedFocusedDisabled
And transitions connecting them.
For this walkthrough we only need Idle, Hover, and Pressed. The extra states are not harmful - unused states are silently ignored at runtime.
If the nodes feel too spread out or the graph has been hand-edited, use the graph toolbar’s layout actions. Compact is usually best for a small button machine, while Flow keeps the initial state and common transition direction easy to read.
Step 7 - Review the states in the Details tab
Section titled “Step 7 - Review the states in the Details tab”Click the Details tab and scroll to the States array. Expand the first few entries to see the defaults.
- Idle -
PlayMode: Loop,AnimationName: Idle - Hover -
PlayMode: Play Once,AnimationName: Hover - Pressed -
PlayMode: Play Once,AnimationName: Pressed
These defaults already match the animation names you created in Step 3. If your animation names differ, update AnimationName here.
Step 8 - Review the transitions
Section titled “Step 8 - Review the transitions”Scroll to the Transitions array in the Details tab, or just read the arrows in the Graph tab.
The Button preset has:
Idle -> Hover- Manual (triggered by callingGoToState)Hover -> Idle- ManualHover -> Pressed- ManualPressed -> Hover- On Animation Finished
The Pressed -> Hover transition fires automatically when the Pressed animation finishes playing. You do not need to call GoToState for that one.
Save the asset with Ctrl+S.
Step 9 - Add a variable to the Widget Blueprint
Section titled “Step 9 - Add a variable to the Widget Blueprint”- Open
WBP_Buttonin the Widget Blueprint editor. - Click the Graph tab.
- In the My Blueprint panel on the left, click the + button next to Variables.
- Name the new variable
StateMachine. - In the Details panel on the right, change its Variable Type to
WbpAnimStateMachine(search for it). Make sure it is an Object Reference, not a class reference or struct. - Leave Instance Editable unchecked.
Step 10 - Create and initialize the machine on Construct
Section titled “Step 10 - Create and initialize the machine on Construct”- In the Event Graph, find or add the Event Construct node (right-click -> search “Construct”).
- Right-click on an empty area of the graph and search for Create And Initialize State Machine.
- Connect the Exec output of Event Construct to the input of Create And Initialize State Machine.
- On the Create And Initialize State Machine node:
- Target: connect
Self(right-click -> “Get a reference to self” or type “Self” in the search). - Definition: click the asset picker and select
DA_Button.
- Drag the Return Value pin of the node and choose Set ->
StateMachine. This stores the machine in the variable you created.
Your graph should now read:
Event Construct -> Create And Initialize State Machine -> Set StateMachineStep 11 - Add On Mouse Enter and On Mouse Leave overrides
Section titled “Step 11 - Add On Mouse Enter and On Mouse Leave overrides”- In the My Blueprint panel, scroll down to Functions -> Override.
- Click Override and choose On Mouse Enter.
- An override function node appears. Inside it, right-click and search Go To WBP State.
- Connect the exec flow into the Go To WBP State node.
- On the Go To WBP State node:
- Target: drag a Get StateMachine node and connect it.
- State: type
Hover. - State Definition: click the picker and select
DA_Button(this enables the state name dropdown - you can also just type the name).
- Repeat for On Mouse Leave, choosing state
Idle.
Step 12 - Add On Mouse Button Down
Section titled “Step 12 - Add On Mouse Button Down”- Override On Mouse Button Down (same Override button in My Blueprint).
- Add a Go To WBP State node inside it, connecting the machine and state
Pressed. - At the end of the function, add a Return Node with Return Value = Handled - this tells Unreal the widget consumed the mouse event.
Note:
On Mouse Button Downrequires the widget to be focusable or to have Is Volatile enabled, and it only fires for the left mouse button by default. If the node never fires in PIE, check that the widget has Is Focusable checked in the Details panel of the Designer tab.
Step 13 - Add the widget to a level
Section titled “Step 13 - Add the widget to a level”To see the button in PIE you need to add it to the viewport from somewhere. The simplest place for testing is the Level Blueprint.
- In the main editor toolbar, click Blueprints -> Open Level Blueprint.
- In the Level Blueprint event graph, right-click and add Event Begin Play.
- Right-click and search Create Widget. Select it.
- On the Create Widget node, set Class to
WBP_Button. - Drag from the Return Value pin and search for Add to Viewport. Connect it.
Event Begin Play -> Create Widget (WBP_Button) -> Add to Viewport- Save and close the Level Blueprint.
Step 14 - Test in PIE
Section titled “Step 14 - Test in PIE”Press Play in the Unreal editor.
- Move the mouse over the button area. The hover animation should play.
- Move the mouse away. The idle animation should restart.
- Click the button. The pressed animation plays, then automatically transitions back to hover when it finishes.
If nothing happens, continue to the Debugging section below.
Debugging the button
Section titled “Debugging the button”Open DA_Button in the asset editor and switch to the Debugger tab. Press Play in the main editor window. The Debugger tab should now show one live machine instance.
Look at:
- Current State - this should change as you hover and click.
- Transition Log - each attempt to transition is logged here, including blocked attempts and the reason they were blocked.
- Blackboard - empty for this walkthrough, that is fine.
Common problems
Section titled “Common problems”“Nothing happens when I hover”
- Check that
On Mouse Enteris connected correctly and reaches theGo To WBP Statenode. - Open the Debugger tab and look at the Transition Log while hovering. If a transition attempt appears but is blocked, it will show the reason.
- Confirm the transition
Idle -> Hoverexists in the definition’s Transitions array. The preset should have added it.
“The animation name is wrong”
- Open the Details tab of the definition. Expand the
Hoverstate in the States array. Check thatAnimation Namematches the exact name of the animation in the widget. The names are case-sensitive.
“Pressed goes back to Idle instead of Hover”
- The
Pressed -> Hovertransition hasTrigger: On Animation Finished. When the Pressed animation ends, it goes to Hover automatically. That is correct behavior. ThenHover -> Idlefires when you explicitly callGoToState(Idle)on mouse leave. - If you want
Pressedto return directly toIdle, change thePressed -> Hovertransition toPressed -> Idle.
Walkthrough 2: Modal Dialog
Section titled “Walkthrough 2: Modal Dialog”Goal: A modal panel that plays an intro animation when it opens, sits in an idle state, plays an outro animation when dismissed, then removes itself from the viewport.
Time estimate: 25-35 minutes.
What you will build
Section titled “What you will build”A Widget Blueprint with four states: Hidden, Intro, Idle, and Outro. The transitions between Intro -> Idle and Outro -> Hidden fire automatically when those animations finish. The widget removes itself from the viewport when it enters the Hidden state.
Step 1 - Create the Widget Blueprint
Section titled “Step 1 - Create the Widget Blueprint”- In the Content Browser, right-click -> User Interface -> Widget Blueprint.
- Name it
WBP_Modal. - Open it.
- In the Designer tab, add an
ImageorSizeBoxto represent the modal panel. - Name the root element
ModalPanelin the Hierarchy.
Step 2 - Create four UMG animations
Section titled “Step 2 - Create four UMG animations”In the Animations panel, create:
Hidden
Section titled “Hidden”A single keyframe with ModalPanel at opacity 0 (or scale 0). Because this is a loop animation used as a persistent “invisible” state, set just one keyframe at time 0.
Keyframe the panel from invisible to fully visible over about 0.3 seconds. For example:
- At time 0: opacity 0, scale (0.9, 0.9)
- At time 0.3: opacity 1, scale (1.0, 1.0)
A looping animation while the modal is fully visible. This can be a single keyframe at full opacity and normal scale - no movement needed. The machine will hold here until dismissed.
The reverse of Intro:
- At time 0: opacity 1, scale (1.0, 1.0)
- At time 0.25: opacity 0, scale (0.9, 0.9)
Step 3 - Create the Definition Asset
Section titled “Step 3 - Create the Definition Asset”- Content Browser -> Miscellaneous -> Data Asset -> WbpAnimStateMachineDefinition.
- Name it
DA_Modal. - Open it.
- In Details, set Owner Widget Class to
WBP_Modal.
Step 4 - Apply the Panel preset
Section titled “Step 4 - Apply the Panel preset”- Set Preset To Apply to Panel.
- Click Apply Preset.
The Panel preset creates a Hidden -> Intro -> Idle -> Outro -> Hidden flow with finish-driven transitions already wired.
Switch to the Graph tab and confirm you can see the four state nodes connected in a ring.
Step 5 - Verify the state configurations
Section titled “Step 5 - Verify the state configurations”Click the Details tab and expand each state:
Hidden
PlayMode: LoopAnimationName:Hidden
Intro
PlayMode: Play OnceAnimationName:Intro
Idle
PlayMode: LoopAnimationName:Idle
Outro
PlayMode: Play OnceAnimationName:Outro
Make sure the AnimationName values match the names you created in Step 2.
Step 6 - Add an ExitFunctionName to the Hidden state
Section titled “Step 6 - Add an ExitFunctionName to the Hidden state”When the machine enters Hidden, we want the widget to remove itself from the viewport. We can do this by pointing the state at a widget function.
- Expand the Hidden state entry in the States array.
- Find the Exit Function Name field and leave it blank - we want the entry callback for
Hidden, not exit. - Find Entry Function Name.
- Type
HandleHidden- this is the function we will create in the widget Blueprint.
Entry Function Name calls a function on the owning widget when the machine enters this state. The function must have no parameters and must be a regular Blueprint function (not an event).
Save the definition with Ctrl+S.
Step 7 - Add variables and functions to WBP_Modal
Section titled “Step 7 - Add variables and functions to WBP_Modal”Open WBP_Modal in the Widget Blueprint editor.
Add the StateMachine variable
Section titled “Add the StateMachine variable”- In My Blueprint -> Variables, click
+. - Name it
StateMachine, typeWbpAnimStateMachine Object Reference.
Add the HandleHidden function
Section titled “Add the HandleHidden function”- In My Blueprint -> Functions, click
+. - Name it
HandleHidden. - Inside the function, right-click and search Remove from Parent.
- Connect the exec flow into Remove from Parent.
This function will be called by the machine when the Hidden state is entered.
Step 8 - Create and initialize the machine on Construct
Section titled “Step 8 - Create and initialize the machine on Construct”- Open the Event Graph tab.
- Add Event Construct.
- Add Create And Initialize State Machine:
- Target: Self
- Definition: DA_Modal
- Connect Return Value to Set StateMachine.
Event Construct -> Create And Initialize State Machine (DA_Modal) -> Set StateMachineStep 9 - Add an Open function
Section titled “Step 9 - Add an Open function”We want other Blueprints to be able to open the modal. A clean pattern is to expose a public function.
- In My Blueprint -> Functions, click
+. - Name it
Open. Make sure Access Specifier is Public in the Details panel on the right. - Inside the function, add a Go To WBP State node:
- Target: Get StateMachine
- State:
Intro - State Definition: DA_Modal
Open function -> Go To WBP State (Intro)Step 10 - Add a Close function
Section titled “Step 10 - Add a Close function”- Add another public function named
Close. - Inside it, add Go To WBP State:
- State:
Outro
Close function -> Go To WBP State (Outro)The machine will play the Outro animation, and when it finishes, automatically transition to Hidden, which calls HandleHidden, which removes the widget from the viewport.
Step 11 - (Optional) Add a confirm button
Section titled “Step 11 - (Optional) Add a confirm button”If your modal has a confirm button inside it:
- Select the button widget in the Hierarchy.
- In the Details panel, scroll to Events and click + next to On Clicked.
- A new event node appears in the Event Graph.
- Add a Go To WBP State node from the On Clicked event:
- State:
Outro
One call to GoToState(Outro) dismisses the modal, plays the outro, removes itself from the viewport - no additional wiring needed.
Step 12 - Create the modal from another Blueprint
Section titled “Step 12 - Create the modal from another Blueprint”Open the Level Blueprint (or whichever Blueprint should show the modal).
- Add Event Begin Play (or a key press event such as
M). - Add Create Widget:
- Class:
WBP_Modal
- Drag from Return Value -> Add to Viewport.
- Drag from Return Value again -> Open (the function you created on the widget).
Key M pressed-> Create Widget (WBP_Modal)-> Add to Viewport-> OpenStep 13 - Test in PIE
Section titled “Step 13 - Test in PIE”Press Play. Press M (or whatever key you used). The modal should:
- Appear from invisible via the Intro animation.
- Sit in Idle (looping its idle animation, or holding).
- When dismissed (if you added a close button), play the Outro.
- Disappear when Outro finishes.
Open DA_Modal in the asset editor and switch to the Debugger tab while PIE is running to watch the state changes in real time.
Debugging the modal
Section titled “Debugging the modal””The modal appears immediately without the intro animation”
Section titled “”The modal appears immediately without the intro animation””- Check that the
Initial Stateon the definition is set toHidden. If it is set toIdle, the machine starts in Idle and skips Intro. - In the Debugger tab, look at Current State immediately after the widget is added to the viewport. It should be
Hidden.
”The modal never removes itself”
Section titled “”The modal never removes itself””- Open the definition Details tab. Confirm that the Entry Function Name on the
Hiddenstate is exactlyHandleHidden- check for typos, extra spaces, or wrong casing. - In My Blueprint, confirm the function is named
HandleHidden(not an event, a regular function). - The function picker in the state’s Entry Function Name field shows valid functions from
OwnerWidgetClass. IfHandleHiddendoes not appear in the picker, double-check thatOwner Widget Classis set toWBP_Modal.
”Outro plays but then nothing happens”
Section titled “”Outro plays but then nothing happens””- Verify that the
Outro -> Hiddentransition has Trigger set to On Animation Finished. - Check that the
Outroanimation in the widget has actual keyframes - an animation with zero duration may finish instantly and the timing can behave unexpectedly. - Look at the Transition Log in the Debugger. A blocked transition entry will show the reason.
Walkthrough 3: Toast Notification
Section titled “Walkthrough 3: Toast Notification”Goal: A toast (brief on-screen message) that appears, waits a configurable number of seconds, then dismisses itself. It should also be dismissible early by a close button.
Time estimate: 20-30 minutes.
What you will build
Section titled “What you will build”A widget with three states - Spawn, Visible, and Dismiss - where Visible uses an auto-transition to move to Dismiss after a set delay. The blackboard stores the auto-dismiss duration.
Step 1 - Create WBP_Toast
Section titled “Step 1 - Create WBP_Toast”- Content Browser -> Widget Blueprint. Name it
WBP_Toast. - In the Designer tab, add:
- A Canvas Panel at the root.
- An Image for the background.
- A Text Block named
MessageTextfor the toast message. - A small Button named
CloseButtonfor early dismissal.
- Arrange them how you like.
Step 2 - Create three animations
Section titled “Step 2 - Create three animations”- Slide in from below or fade in over 0.25 seconds.
- Example: at time 0, offset
(0, 60)and opacity 0. At time 0.25, offset(0, 0)and opacity 1.
Visible
Section titled “Visible”- A short looping animation (can be a gentle pulse or just hold at full opacity).
- Because it loops, the machine stays here until something moves it out.
Dismiss
Section titled “Dismiss”- Reverse of Spawn: fade and slide out over 0.25 seconds.
Step 3 - Create DA_Toast
Section titled “Step 3 - Create DA_Toast”- Content Browser -> Data Asset -> WbpAnimStateMachineDefinition. Name it
DA_Toast. - Open it.
- Set Owner Widget Class to
WBP_Toast.
Step 4 - Apply the Toast preset
Section titled “Step 4 - Apply the Toast preset”- Preset To Apply: Toast.
- Apply Preset.
This gives you Spawn -> Visible -> Dismiss with:
Spawn -> Visibletrigger: On Animation FinishedVisible -> Dismisstrigger: Manual (you will add an auto-transition in the next step)Dismisshas an on-finish transition that removes the widget
Step 5 - Configure the auto-transition on Visible
Section titled “Step 5 - Configure the auto-transition on Visible”The Visible state should automatically move to Dismiss after N seconds.
- In the Details tab, find the Visible state in the States array.
- Expand it.
- Set Auto Transition Delay to
3.0(three seconds). - Set Auto Transition State to
Dismiss.
Now, three seconds after the machine enters Visible, it will automatically call GoToState(Dismiss) without any Blueprint wiring.
Tip: You can make this configurable by using a blackboard value instead. See the optional step below.
Step 6 - Wire HandleDismiss
Section titled “Step 6 - Wire HandleDismiss”The Dismiss animation plays once and then… what? The preset’s Dismiss state should have an OnAnimationFinished transition to a Hidden state, or alternatively you can wire a function.
If the preset added a Hidden state, add Entry Function Name = HandleHidden to it, and create a HandleHidden function in the widget that calls Remove From Parent.
If not, add it manually:
- In the Details tab, click the + button next to the States array to add a new state.
- Name it
Hidden. - Set Animation Name to
Hidden(create a matching trivial animation in the widget, or leave it blank if you do not need one). - Set Entry Function Name to
HandleHidden. - In the Transitions array, add a new entry:
- From State:
Dismiss - To State:
Hidden - Trigger: On Animation Finished
- Save the definition.
Back in WBP_Toast, add a function named HandleHidden that calls Remove From Parent.
Step 7 - Wire the close button
Section titled “Step 7 - Wire the close button”- In WBP_Toast, select
CloseButtonin the Hierarchy. - In the Details panel, click + next to On Clicked.
- In the event node that appears, add Go To WBP State:
- Target: Get StateMachine
- State:
Dismiss
Step 8 - Add a SetMessage function
Section titled “Step 8 - Add a SetMessage function”A toast is only useful if you can set its message text. Add a public function:
- My Blueprint -> Functions ->
+. Name itSetMessage. - Add an input parameter: Name
Message, TypeText. - Inside the function, drag from
Message-> Set Text (Text Block), targetingMessageText.
Step 9 - Create and initialize the machine in WBP_Toast
Section titled “Step 9 - Create and initialize the machine in WBP_Toast”In the Event Graph:
Event Construct-> Create And Initialize State Machine (DA_Toast)-> Set StateMachineAfter initializing, call Go To WBP State (Spawn) to begin the appearance animation immediately:
Event Construct-> Create And Initialize State Machine (DA_Toast)-> Set StateMachine-> Go To WBP State (Spawn)Step 10 - Spawn the toast from another Blueprint
Section titled “Step 10 - Spawn the toast from another Blueprint”Open the Level Blueprint (or HUD Blueprint):
Key T pressed-> Create Widget (WBP_Toast)-> Add to Viewport-> Set Message (Message = "Save complete!")You do not need to call Open separately because the machine automatically starts in Spawn (assuming the definition’s Initial State is Spawn) and drives the animation itself.
Step 11 - Test in PIE
Section titled “Step 11 - Test in PIE”Press Play, then press T. The toast should:
- Slide in from below.
- Sit visible for three seconds.
- Slide out and remove itself.
Pressing the close button at any point should immediately begin the dismiss animation.
Optional: Make the duration configurable via the Blackboard
Section titled “Optional: Make the duration configurable via the Blackboard”Instead of hard-coding 3.0 seconds in the definition:
- Set Auto Transition Delay on
Visibleback to0. - Open
WBP_Toast’s Event Construct. - After creating the machine, call Set Blackboard Float:
- Target: Get StateMachine
- Key:
AutoDismissSeconds - Value:
3.0(or expose this as a variable that callers can set before spawning)
- Back in the definition, on the
Visiblestate’s auto-transition, check whether the definition supports a blackboard-driven delay rule.
Alternatively - and more simply - just leave the hard-coded delay and expose a SetDuration function on the widget that sets a float variable, then use that variable in the Rule for the Visible -> Dismiss transition via a BlackboardFloat > Value rule block.
Debugging the toast
Section titled “Debugging the toast””The toast appears but never auto-dismisses”
Section titled “”The toast appears but never auto-dismisses””- Open the definition Details tab. Find the Visible state. Confirm Auto Transition Delay is greater than 0 and Auto Transition State is
Dismiss. - In the Debugger, watch Time In State while the machine is in Visible. It should count up. When it reaches the delay value, the transition should fire.
”The toast removes itself immediately”
Section titled “”The toast removes itself immediately””- The
Spawnstate’s animation may have zero duration. Check that the Spawn animation has actual keyframes with a duration. - Alternatively, the machine may be starting in
Visibleinstead ofSpawn. Check Initial State on the definition - it should beSpawn.
”The close button does not dismiss early”
Section titled “”The close button does not dismiss early””- Confirm the
Visible -> DismissManual transition exists in the Transitions array. The auto-transition covers the delay path; the Manual transition covers the close-button path. Both can exist simultaneously.
Walkthrough 4: Tab Panel with Parallel Tracks
Section titled “Walkthrough 4: Tab Panel with Parallel Tracks”Goal: A panel widget with three tabs. Each tab has its own selected and unselected animations. A separate animation track handles the panel’s show/hide flow independently from the tab selection state.
Time estimate: 35-45 minutes.
Why this uses two tracks
Section titled “Why this uses two tracks”Without parallel tracks, every combination of “which tab is selected” and “is the panel visible” would require its own state. You end up with states like Visible_Tab1, Visible_Tab2, Hidden_Tab1, and so on - a combinatorial explosion.
With two tracks:
- Base track:
Hidden -> Intro -> Idle -> Outro -> Hidden - Tabs track:
Tab1 -> Tab2 -> Tab3(and back)
They run independently. You control them separately. The panel’s show/hide behavior never interferes with tab selection.
Step 1 - Create WBP_TabPanel
Section titled “Step 1 - Create WBP_TabPanel”- Content Browser -> Widget Blueprint. Name it
WBP_TabPanel. - In the Designer tab, create a layout with:
- Three tab buttons named
Tab1Button,Tab2Button,Tab3Button - A content area below the tabs (an Image or Border panel)
- The tab buttons should visually indicate which one is selected.
Step 2 - Create animations for the Base track
Section titled “Step 2 - Create animations for the Base track”These animations control the panel’s overall show/hide flow.
Intro- fade/slide the entire panel in over 0.3 secondsIdle- hold at full opacity, loopOutro- fade/slide out over 0.25 secondsHidden- invisible hold
Step 3 - Create animations for the Tabs track
Section titled “Step 3 - Create animations for the Tabs track”These animations control the selected state of each tab.
Tab1- Tab1Button is highlighted; Tab2 and Tab3 are at reduced opacityTab2- Tab2Button is highlighted; others are reducedTab3- Tab3Button is highlighted; others are reduced
Each should be a looping animation so the machine holds the selected state until you explicitly switch tabs.
Step 4 - Create two Definition Assets
Section titled “Step 4 - Create two Definition Assets”You need two separate definition assets - one per track.
DA_TabPanel_Base
Section titled “DA_TabPanel_Base”- Content Browser -> Data Asset -> WbpAnimStateMachineDefinition. Name it
DA_TabPanel_Base. - Open it. Set Owner Widget Class to
WBP_TabPanel. - Apply the Panel preset.
- Confirm
Intro,Idle,Outro,Hiddenstates are present. - Add
HandleHiddenas the Entry Function of theHiddenstate (same as the Modal walkthrough). - Save.
DA_TabPanel_Tabs
Section titled “DA_TabPanel_Tabs”- Create another definition asset:
DA_TabPanel_Tabs. - Open it. Set Owner Widget Class to
WBP_TabPanel. - Do not apply a preset - add states manually.
In the Details tab:
-
Click + next to States three times.
-
Configure each:
State 1
-
StateName:Tab1 -
AnimationName:Tab1 -
PlayMode: Loop
State 2
StateName:Tab2AnimationName:Tab2PlayMode: Loop
State 3
-
StateName:Tab3 -
AnimationName:Tab3 -
PlayMode: Loop -
Set Initial State to
Tab1.
In the Transitions array, add six entries for full two-way navigation:
| From | To | Trigger |
|---|---|---|
| Tab1 | Tab2 | Manual |
| Tab1 | Tab3 | Manual |
| Tab2 | Tab1 | Manual |
| Tab2 | Tab3 | Manual |
| Tab3 | Tab1 | Manual |
| Tab3 | Tab2 | Manual |
Save.
Step 5 - Create a WbpAnimStateMachineGroup in WBP_TabPanel
Section titled “Step 5 - Create a WbpAnimStateMachineGroup in WBP_TabPanel”The group is the host object that holds both tracks.
- Open
WBP_TabPanelWidget Blueprint. - In the Graph tab, My Blueprint -> Variables -> +. Name it
MachineGroup, typeWbpAnimStateMachineGroup Object Reference. - Also add a separate variable
BaseMachineof typeWbpAnimStateMachine Object Reference(optional - you can always retrieve the track by name from the group, but storing the reference is convenient).
Step 6 - Set up the group in Event Construct
Section titled “Step 6 - Set up the group in Event Construct”In the Event Graph:
- Add Event Construct.
- Right-click -> search Create State Machine Group. Add it.
- Target: Self
- Connect
Return Value-> Set MachineGroup. - Drag from Get MachineGroup -> Add Track:
- Track Name:
Base - Definition: DA_TabPanel_Base
- Drag from Return Value of Add Track -> Set BaseMachine (for convenience).
- Add another Add Track call:
- Track Name:
Tabs - Definition: DA_TabPanel_Tabs
Your Event Construct should read:
Event Construct-> Create State Machine Group (Self)-> Set MachineGroup
Get MachineGroup-> Add Track (Base, DA_TabPanel_Base) -> Set BaseMachine-> Add Track (Tabs, DA_TabPanel_Tabs)Step 7 - Tick the group
Section titled “Step 7 - Tick the group”The group needs to be ticked to evaluate time-based conditions, focus detection, and auto-transitions.
- In My Blueprint -> Functions -> Override, find and add On Tick.
- Inside On Tick, add Tick Group (search for it):
- Target: Get MachineGroup
- Delta Time: connect the
Delta Secondspin from the On Tick event.
Step 8 - Add Open and Close functions
Section titled “Step 8 - Add Open and Close functions”- Add a public function
Open. - Inside it, Go To State On Track:
- Target: Get MachineGroup
- Track Name:
Base - State:
Intro
- Add a public function
Close. - Inside it, Go To State On Track:
- Target: Get MachineGroup
- Track Name:
Base - State:
Outro
HandleHidden (same as before)
Section titled “HandleHidden (same as before)”- Add a regular function
HandleHidden. - Inside it: Remove From Parent.
Step 9 - Add tab button click handlers
Section titled “Step 9 - Add tab button click handlers”For each tab button, wire an On Clicked event to Go To State On Track targeting the Tabs track:
Tab1Button -> On Clicked
On Clicked (Tab1Button)-> Go To State On Track Target: Get MachineGroup Track Name: Tabs State: Tab1Repeat for Tab2 and Tab3.
Step 10 - Test in PIE
Section titled “Step 10 - Test in PIE”- Open the Level Blueprint.
- On a key press: Create Widget (WBP_TabPanel) -> Add to Viewport -> Open.
- Press Play. Press the key.
The panel should:
- Slide in via the Base track’s Intro.
- Land in Idle.
- Clicking tab buttons should switch the tab highlight animation on the Tabs track.
- Tab switching should not affect the panel’s show/hide state.
- Calling Close should play the Outro animation and remove the panel.
Debugging the tab panel
Section titled “Debugging the tab panel””Only one track is working”
Section titled “”Only one track is working””- Open the debugger. The machine instance list shows all active machines by definition. Confirm you see two active machines - one for DA_TabPanel_Base and one for DA_TabPanel_Tabs.
- If only one appears, check that both
Add Trackcalls in Event Construct are connected correctly.
”Tab switching works but the panel never appears”
Section titled “”Tab switching works but the panel never appears””- Confirm the Base track’s machine was created. Check Go To State On Track - make sure Track Name is spelled
Baseexactly (case-sensitive).
”On Tick override is not available in my widget”
Section titled “”On Tick override is not available in my widget””On Tickis only available in Widget Blueprints if Tick Frequency is not set to Never. In the Designer tab, select the widget root and check the Details panel. Set Tick Frequency to Auto or Always under Widget -> Tick Frequency.
Walkthrough 5: Curve Atlas Timed Sequence
Section titled “Walkthrough 5: Curve Atlas Timed Sequence”Goal: Create a state that animates widget properties from a UCurveLinearColor row instead of a UMG animation timeline.
Time estimate: 15-25 minutes if you already have a Widget Blueprint and state machine definition.
What you will build
Section titled “What you will build”A small Pulse state that fades and scales a widget by sampling a color curve over time. The state can play once and then transition back to Idle, or loop until another state is requested.
Step 1: Create or choose a widget target
Section titled “Step 1: Create or choose a widget target”- Open your Widget Blueprint.
- Pick a visible widget such as an
Image,Border, or panel. - Give it a stable name, for example
PulseTarget. - Save the Widget Blueprint.
You can leave the binding widget name empty later if you want to drive the owning widget itself, but naming the target makes the setup easier to read.
Step 2: Create a linear color curve
Section titled “Step 2: Create a linear color curve”- In the Content Browser, create a
Curve Linear Colorasset. - Name it something like
C_UI_Pulse. - Edit the curve so time
0.0represents the start value and time1.0represents the end value. - Use the RGBA channels as property values. For example:
R: opacityG: X scaleB: Y scaleA: optional visibility or secondary scalar
For a simple pulse, set values so opacity rises from 0.6 to 1.0, and scale rises from 1.0 to 1.08.
Step 3: Optional Curve Atlas
Section titled “Step 3: Optional Curve Atlas”If your project uses Curve Atlases for shared UI curves:
- Add the
C_UI_Pulserow to aCurve Linear Color Atlas. - Assign that atlas in the state binding later.
The runtime evaluates the curve row directly. The atlas reference is used for authoring clarity and validation, so the editor can warn when a binding points at a curve that is not registered in the selected atlas.
Step 4: Add the state
Section titled “Step 4: Add the state”- Open the
WbpAnimStateMachineDefinition. - Add a state named
Pulse. - Leave
AnimationNameempty if this state should be curve-only. - Set
PlayMode:
Play Onceif the pulse should finish and move on.Loopif the pulse should keep running.PingPongif the pulse should breathe back and forth.
- Set
CurveAtlasDuration, for example0.35.
Step 5: Add curve atlas bindings
Section titled “Step 5: Add curve atlas bindings”In the Pulse state’s CurveAtlasBindings array, add bindings such as:
WidgetName:PulseTargetCurve:C_UI_PulseAtlas: your atlas asset, if usedProperty:Render OpacityScalar Channel:R
Add a second binding for scale:
WidgetName:PulseTargetCurve:C_UI_PulseProperty:Render Scale
For vector properties such as render scale, the binding reads the sampled curve’s R and G channels as X and Y.
Step 6: Add transitions
Section titled “Step 6: Add transitions”For a one-shot pulse:
- Add a manual transition from
IdletoPulse. - Add an
On Animation Finishedtransition fromPulseback toIdle. - Keep
Pulseset toPlay Once.
Curve-only finite states use the same finish path as UMG animation-backed states, so the On Animation Finished transition still works when CurveAtlasDuration completes.
Step 7: Make sure MachineTick runs
Section titled “Step 7: Make sure MachineTick runs”Curve Atlas sequences are tick-driven. In the owning widget, make sure MachineTick(DeltaTime) runs from the widget’s tick path, the same way you would for notifies or tick conditions.
If MachineTick is not called, the state can still enter, but the curve sequence will not advance.
Step 8: Test and validate
Section titled “Step 8: Test and validate”- Play in editor.
- Trigger
Go To WBP StatewithPulse. - Confirm the widget property changes over the configured duration.
- If the state is one-shot, confirm it returns to
Idle. - Run validation in the state machine editor.
Common warnings:
CurveAtlasDurationis set but no bindings exist.- Bindings exist but duration is
0. - A binding has no curve row.
- A curve row is not registered in the selected atlas.
Walkthrough 6: GAS Event-Driven UI State
Section titled “Walkthrough 6: GAS Event-Driven UI State”This walkthrough shows how to route Gameplay Ability System event tags into a Widget Blueprint state machine without making every ability manually call GoToState.
Example use cases:
- hit-react UI
- low-health pulse
- ability cooldown flash
- death or disabled overlay
Step 1: Create the states
Section titled “Step 1: Create the states”In your definition asset, add states such as:
IdleHitReactLowHealthDead
Set each state’s AnimationName to the matching Widget Blueprint animation, or leave it empty if the state is driven by Curve Atlas bindings or entry functions.
Step 2: Add normal transitions
Section titled “Step 2: Add normal transitions”Add the transitions that should be legal during normal play:
Idle -> HitReactHitReact -> IdlewithOn Animation FinishedIdle -> LowHealthLowHealth -> IdleAny -> Deadif death should be reachable from anywhere
Use normal transitions where possible. They keep the state graph honest and make blocked behavior easier to debug.
Step 3: Add GAS Event Bindings
Section titled “Step 3: Add GAS Event Bindings”In the definition’s GAS Events array, add entries like:
EventTag:Gameplay.DamageTargetState:HitReactbForce: falseCallerPriority: 0
Add another entry:
EventTag:Gameplay.Health.LowTargetState:LowHealthbForce: falseCallerPriority: 0
Tags are matched with FGameplayTag::MatchesTag, so a binding for Gameplay.Damage also matches Gameplay.Damage.Fire and Gameplay.Damage.Ice. Use a more specific tag if you only want one event.
Step 4: Forward GAS events at runtime
Section titled “Step 4: Forward GAS events at runtime”The state machine does not subscribe to UAbilitySystemComponent automatically. Forward the event from your gameplay code or Blueprint listener:
AbilitySystem->AddGameplayEventTagContainerDelegate( FGameplayTagContainer(DamageTag), FGameplayEventTagMulticastDelegate::FDelegate::CreateWeakLambda(this, [StateMachine](FGameplayTag Tag, const FGameplayEventData*) { if (StateMachine) { StateMachine->HandleGameplayEvent(Tag); } }));Blueprint flow:
- Subscribe to the gameplay event.
- Get the widget’s state machine reference.
- Call Handle Gameplay Event with the incoming tag.
- Use the returned integer to see how many bindings successfully triggered.
Step 5: Understand multiple matches
Section titled “Step 5: Understand multiple matches”If multiple GAS bindings match the same incoming tag, they are evaluated in declaration order. Each GoToState call is independent, so the second matching binding runs from whatever state the first binding left the machine in.
That means this setup:
Gameplay.Damage -> HitReactGameplay.Damage -> LowHealth
can attempt both transitions. The second attempt may succeed or fail depending on whether HitReact -> LowHealth is legal after the first binding runs.
Step 6: Use force carefully
Section titled “Step 6: Use force carefully”bForce bypasses the transition table, but it does not bypass interrupt protection. If the current state has InterruptPriority = 10, a GAS binding with bForce = true and CallerPriority = 0 will still be rejected.
Use force for genuinely urgent states such as death, disconnect, or modal shutdown:
EventTag:Gameplay.DeathTargetState:DeadbForce: trueCallerPriority: 100
Step 7: Validate and debug
Section titled “Step 7: Validate and debug”Press Validate State Machine. Validation checks that:
- every GAS event tag is valid
- every GAS binding target state exists
Then test in PIE with the Debugger tab open. The transition log is the best place to see whether a gameplay event matched no binding, matched a binding but failed transition rules, or was blocked by interrupt priority.
General Tips and Common Mistakes
Section titled “General Tips and Common Mistakes”Tip 1: State names and animation names are case-sensitive
Section titled “Tip 1: State names and animation names are case-sensitive”The machine compares AnimationName exactly against the list of animations on the widget. hover and Hover are different names. When nothing plays but the machine transitions correctly, the first place to check is the case of the animation name.
Tip 2: Always set OwnerWidgetClass
Section titled “Tip 2: Always set OwnerWidgetClass”Without OwnerWidgetClass set on the definition, the animation name dropdowns are empty, function dropdowns are empty, and validation cannot catch name mismatches. Set it first, before doing anything else.
Tip 3: Use the Debugger tab, not just print strings
Section titled “Tip 3: Use the Debugger tab, not just print strings”The Debugger tab in the definition asset editor is the fastest way to understand what a machine is doing. It shows:
- The exact current state
- How long the machine has been in that state
- Every transition attempt, including blocked ones with reasons
- Blackboard values live
Open it during PIE instead of adding print strings throughout your Blueprint graphs.
Tip 4: The transition must exist for GoToState to succeed
Section titled “Tip 4: The transition must exist for GoToState to succeed”Calling GoToState(Hover) when you are in Idle will silently fail if there is no Idle -> Hover transition in the definition. The Debugger’s Transition Log will show “No valid transition found” in this case. This is intentional - the machine enforces the authored graph.
To allow a transition from any state (e.g., always allow GoToState(Disabled) regardless of current state), set From State to None on the transition. This is called a wildcard transition.
Tip 5: Use Force when transitions are blocked by rules
Section titled “Tip 5: Use Force when transitions are blocked by rules”If a transition has rules attached and you need to bypass them for one specific call (such as forcibly disabling the widget regardless of current conditions), pass bForce = true in the Go To WBP State node. Force bypasses rule evaluation and the transition table, but it still respects the current state’s InterruptPriority; the caller priority must meet or exceed that value.
Tip 6: One definition asset can power many widgets
Section titled “Tip 6: One definition asset can power many widgets”Multiple widget blueprint instances can use the same DA_Button definition simultaneously. Each gets its own independent runtime machine. The Debugger lists them all and lets you switch between instances.
Tip 7: Apply a preset, then customize
Section titled “Tip 7: Apply a preset, then customize”Presets give you a solid starting graph in seconds. Most real-world buttons and panels need minor adjustments from the preset - a state renamed, a transition removed, a rule added. Starting from a preset is almost always faster than building from scratch.
Tip 8: PlayMode matters for transitions
Section titled “Tip 8: PlayMode matters for transitions”On Animation Finished transitions only fire when the state’s Play Mode is Play Once or Reverse. If a state uses Loop or Ping-Pong, the animation never finishes, so those transitions never fire. If a transition is not firing when the animation ends, check the state’s Play Mode first.
Tip 9: Entry and Exit Functions must be regular functions, not Events
Section titled “Tip 9: Entry and Exit Functions must be regular functions, not Events”Blueprint Events (such as Event BeginPlay or custom events) cannot be called by name from the machine. The Entry Function Name and Exit Function Name fields only work with regular Blueprint Functions (the blue node with an f icon). If you accidentally created a Custom Event instead of a Function, move the logic into a proper function.
Tip 10: The machine’s outer is the widget
Section titled “Tip 10: The machine’s outer is the widget”The machine is created with the widget as its outer object. This means it shares the widget’s lifetime and can call functions on the widget directly. You do not need to pass the widget around separately.
Where to Go Next
Section titled “Where to Go Next”These six walkthroughs cover the most common patterns. Once you are comfortable with them:
- Read the User Guide for the full feature surface, including snapshots, input bindings, sub-state machines, Curve Atlas sequences, and the Sequencer track.
- Use the Anim Workbench Walkthroughs when you want to audit, repair, compare, or bind the Widget Blueprint animation clips that your state machine plays.
- Read the Technical Reference if you are working in C++ or want to understand the internals.
- Use the Native graph implementation history when you need migration context for the current graph editor surface.