State machines

Make a frame's timeline interactive: states that each play a stretch of it, inputs, transitions with conditions, and listeners on layers. Plays in Present, exports to dotLottie and the web.

A state machine makes a frame's animation respond. Each state plays one stretch of the timeline, once or looping. Inputs hold values such as hovered or presses. Listeners change the inputs when someone presses, clicks, enters or leaves a layer. Transitions move the machine from one state to another when their conditions hold. It is the same idea as state machines in Lottie Creator and Rive, built on the timeline you already have.

Try one first

Open New file → Motion, search for Like button and open it. It's a heart run by a machine with four states (Idle, Hover, Like, Unlike), two Boolean inputs (hovered, liked), an event (finished) and a listener of each kind you'll use most: pointer enter and leave on the whole frame, a click on the button, and Finished playing. Press Present, hover the heart, and click it twice. Then click the State machine button on the transport bar to see how it's put together.

A state machine: a like button that answers hover and click · 0:10
Description

The Like button Lottie template in Animate. The State machine button in the transport bar swaps the timeline for the machine’s graph: Idle, Hover, Like and Unlike joined by transitions, with the hovered and liked inputs and the listeners beside it. Picking the Like state shows what it plays. In present mode the pointer moves onto the heart and it grows; a click fills it with a burst, and a second click empties it.

  1. Open the Like button template; it opens in Animate.
  2. Click the State machine button in the transport bar: the graph replaces the timeline's rows.
  3. Pick a state to see what it plays and where its transitions go.
  4. Press Present, then hover the heart and click it twice.

A game built from machines

The Mossy Hollow platformer template (New file → Game UI) is a bigger example: four screens, each with a machine of its own. The tabs at the top move between them, and on every screen an outlined pill shows which state is playing.

  • Level 1-1 runs Pip, the hero. Idle and Run loop. Stomp, Slash and Hurt play once and then go back to Run if RUN is still held, or to Idle if it isn't. Holding the RUN button sets the running Boolean (pointer down sets it true, pointer up sets it false). JUMP and SLASH fire events, clicking Gloop fires hit, and Finished playing fires done.
  • Gloop: enemy AI is a slime that patrols. When the pointer comes into its sight it becomes Alert, then Chases. Click it to squash it, and it respawns. Its sight is a layer with Pointer enter and Pointer leave listeners on it.
  • Flit: enemy is a bat that roosts until the pointer comes into its cave. Then it wakes and flies; click to make it dive. When the pointer leaves, it goes back to roost.
  • ? Block shows a Number input. Bump's On entry action adds one to hits. A transition with the condition hits ≥ 3 empties the block, and RESET sets the count back to zero.
A game run by state machines: a hero and an enemy, each with its own · 0:12
Description

The Mossy Hollow platformer in present mode. Holding RUN switches Pip from Idle to its Run loop and letting go switches back; JUMP plays the Stomp one-shot, SLASH the Slash one-shot, and the outlined pill shows which state is playing. The Gloop tab opens the slime’s own machine: the pointer entering its sight makes it spot you and chase, and a click squashes it.

  1. Press Present: Pip idles.
  2. Hold → (or D, or the RUN button): Pip runs until you let go.
  3. ↑, W or Space jumps and stomps; X or J slashes. Each is a one-shot state.
  4. Gloop has a machine of its own: hold → to move into its sight, then press ↑ to stomp it.
  5. 1–4 switch screens. On Flit's, Space dives; on the ? Block's, ↑ bumps it and R resets it.

Every key has an on-screen button or pointer gesture too, so the game also plays on a phone.

How to

Make a button that reacts to hover and click

  1. Animate the frame's whole story on one timeline: the idle loop, the hover, the press. Put a marker (M) where each part starts and label it (Hover, Press).
  2. In the transport bar, click the State machine button. The rows give way to the machine's graph. Click Create state machine. You get one state per stretch between markers: an Intro before the first marker, then a state for each marker that plays up to the next one.
  3. Under Inputs, add a Boolean and rename it hovered.
  4. Drag from the small circle on the right of the Intro state onto the Hover state. That draws a transition. Pick it, click Condition, and leave it as hovered = true. Draw one back from Hover to Intro with hovered = false.
  5. Under Listeners, add one. Set it to Pointer enter on the button layer, with the action Set hovered true. Add another for Pointer leave that sets it false.
  6. Press Present and hover the button.

Play one stretch on a loop

Pick the state and tick Loop. Speed plays the stretch faster or slower. From and To choose the markers it plays between. Leave To as The next marker to stop at whichever marker comes after From, or at the end.

Go to a state from anywhere

Drag from the Any state pill at the top left onto a state. That transition is checked whatever state the machine is in. It suits an event input such as reset: fire it from a listener and every state jumps to the one you chose.

Edit the graph

The graph is the same editor as the shader node editor, so the gestures are the same in both. Drag a state to move it, or drag across empty space to select several (Shift-click adds or removes one). Drag from a state's handle (the small circle on its right) onto another state to add a transition; let go over empty space instead and you get a new state there, already joined, with its name ready to type. Double-click empty space to add a state, and double-click a state (or pick it and press F2) to rename it. Click an arrow to pick it and edit its conditions on the right.

Right-click a state to rename, duplicate or remove it, make it the first state, or turn its loop on or off. Right-click an arrow to reverse or remove it, and right-click empty space to add a state there or fit the graph. With the graph focused, Delete removes what you picked, Cmd+D duplicates the picked states (with the transitions between them), Cmd+A selects every state, the arrow keys nudge them (Shift for bigger steps), and Escape lets go. Scroll to pan, Cmd+scroll (or pinch) to zoom, and press F to fit the graph. Each edit is one undo step, however many states it moves or adds.

The state machine graph, step by step · 0:26
Description

The Like button template in Animate with its state machine graph open under the canvas: Idle, Hover, Like and Unlike, and Any state. Hover is dragged to the right and its arrows follow. A transition is drawn from Unlike's handle onto Hover. One drawn from Like's handle and let go over empty space makes a new state there, already joined, named Celebrate in place; a double-click on empty space adds another, named Rest. Clicking the arrow from Idle to Hover shows its condition in the inspector. Right-clicking Like opens its menu: Rename, Make first state, Loop, Duplicate and Remove. Double-clicking Unlike renames it Undo like. A marquee selects Rest and Undo like, Cmd+D duplicates them and Delete removes the copies, and Cmd+Z undoes both. Scrolling pans, Cmd+scroll zooms, and F fits the graph.

  1. Drag a state to move it. Its arrows follow.
  2. Drag from a state's handle onto another state to add a transition.
  3. Let go of a transition over empty space: a new state appears there, joined to the first. Type its name and press Enter.
  4. Double-click empty space to add a state, and name it the same way.
  5. Click an arrow: its conditions show on the right.
  6. Right-click a state for its menu: Rename, Make first state, Loop, Duplicate and Remove.
  7. Double-click a state (or press F2) to rename it.
  8. Drag across empty space to select several states.
  9. Cmd+D duplicates them; Delete removes them.
  10. Cmd+Z undoes each change.
  11. Scroll to pan, and Cmd+scroll to zoom.
  12. Press F to fit the graph.

Try it without leaving Animate

Click Play under the graph. The machine runs on the canvas as it does in Present: hover and click the frame's layers and press keys. The state the machine is in lights up green, and so does the arrow that brought it there, with a flash as it is taken. Each input shows its value beside it. Only the machine hears the pointer and keys, so the prototype's own interactions stay put. Escape, Stop, or any edit outside the machine ends it.

Play the machine without leaving Animate · 0:06
Description

The Like button template in Animate with its state machine graph open. Play under the graph starts the machine on the canvas. The pointer moving onto the heart makes it grow, and the Hover state and the arrow into it light up green with the hovered input showing true. A click fills the heart and the Like state lights up; Escape stops the preview.

  1. Click Play under the graph.
  2. Hover the heart: the Hover state and the arrow into it light up, and hovered shows true.
  3. Click it: the machine moves on to Like.
  4. Press Escape to stop.

Inputs, conditions and actions

InputHoldsConditionsActions
Booleantrue or false= and ≠ a valueSet, Toggle, Reset
Numbera number=, ≠, >, ≥, <, ≤ a valueSet, Increase, Decrease, Reset
Textsome text= and ≠ a valueSet, Reset
Eventnothing: it firesholds only as it firesFire

A transition is taken when all its conditions hold. A transition with no conditions is taken as soon as its state is entered, which chains states one after another. When several could be taken, the state's own transitions come first, in the order you made them, then the ones from Any state.

A state's On entry actions run each time the machine enters it: count presses, or set a flag.

Listeners

ListenerHears
Pointer down, Pointer upA press and a release on the layer
ClickA click on the layer
Pointer enter, Pointer leaveThe pointer arriving on or leaving the layer
Finished playingThe current state's stretch reaching its end (not for a looping state)
Key down, Key upA key pressed or let go: the one you set (click the field and press it), or any key

A listener set to The whole frame hears the event anywhere in the frame. A listener on a group hears it on anything inside the group. Key listeners have no layer: they hear the keyboard wherever the pointer is. A key held down counts as one press.

Where it plays

  • Present. The frame starts in its first state and the machine runs as you click, hover and press keys. The prototype's own interactions still work beside it.
  • The state machine panel's Play. The machine alone, on the canvas, while you edit it.
  • dotLottie. Export a .lottie and leave Include state machine on. The file is a dotLottie 2.0 with the machine in it, which dotlottie-web and the dotLottie players for iOS and Android run. Each state's stretch becomes a named Lottie marker, and listeners on a layer find it by its name, so give those layers names of their own. dotLottie has no key interactions, so key listeners are left out and the export says so. A .json export has no machine, but it does keep the timeline's markers.
  • The web. HTML and React exports of the frame carry the machine with a small script. The page can drive it too: element.popcraftMachine.set('hovered', true), .fire('reset'), and a popcraft:state event on every change.
  • Import. Opening a .lottie that has a state machine brings in the first one, with its inputs, transitions and listeners, on the imported frame.

The agent and plugins

The agent builds and edits machines with edit_state_machine and reads them with get_state_machine. Plugins call popcraft.editStateMachine and popcraft.getStateMachine with the same arguments. States, inputs and markers can be named by name instead of id.