States & triggers

States are prefabs with a StateFlowComponent; triggers become ports.

States

A state is anything the flow can be "in": a title screen, a settings popup, a confirmation dialog. In code, a state is a MonoBehaviour deriving from StateFlowComponent. In the graph, it is a node.

Most states are prefab states: a uGUI prefab with the component on its root, loaded and spawned when the flow enters the state and destroyed when it leaves. StateFlow also has script states with no visuals, toasts and global triggers.

StateFlowComponent.cs (members you can override)
public abstract class StateFlowComponent : MonoBehaviour, IStateFlowComponent
{
    public GameObject GameObject { get; }
    public RectTransform RectTransform { get; }

    public virtual void Initialize() { }          // spawned: wire up the UI
    public virtual void LateInitialize() { }      // after the payload is set
    public virtual void Enter() { }               // became the active state
    public virtual void TransitionFinished() { }  // the transition into it ended
    public virtual void Exit() { }                // another state became active
    public virtual void Dispose() { }             // about to be destroyed
}

The Lifecycle page explains exactly when each method runs.

Triggers

A trigger is a public event of one of StateFlow's Trigger delegate types. Every trigger becomes an output port on the state's node, named after the event. Invoking the event moves the flow along the transition drawn from that port.

DeclarationPortCarries
public event Trigger Back;BackNothing
public event Trigger<LevelData> StartLevel;StartLevel<LevelData>One payload
public event Trigger<ShopItem, int> Buy;Buy<ShopItem, Int32>Two payloads
SettingsPopup.cs
public class SettingsPopup : StateFlowComponent
{
    [SerializeField] private Button closeButton;

    public event Trigger Close;

    public override void Initialize()
    {
        closeButton.onClick.AddListener(() => Close?.Invoke());
    }
}

A state never refers to the state its trigger leads to. That is the graph's job, so one screen can lead to different places in different games, or in different branches of the same game.

Tip

Only the active state's triggers are connected. Invoking a trigger on a state that has already been left does nothing, so you don't need to guard against double taps during a transition. A state covered by a popup is ignored too, but StateFlow logs a warning naming the state and trigger, because that usually means a result arrived while the player was looking at something else. Raise it after the state's Enter, or record the outcome in a model.

Triggers on child objects

Any StateFlowComponent in the prefab's hierarchy contributes its triggers, not only the root. A reusable currency bar can carry its own OpenStore trigger and show up as a port on every screen it is part of. See Spawned content.

The node

Select a state to see it in the info panel on the left of the graph. There you can rename it, change its layer and mark it as an entry or exit state. Its prefab and State Asset are linked from the panel too.

StateFlow Editor — info panel
The Main Menu node is selected and the info panel shows its name, Screen layer, Entry and Exit flags, prefab, State Asset and asset id.
A node's header shows its name, entry or exit icon and layer. Below that come the script name and one port per trigger.

Renaming and refactoring

Transitions are stored against the script's full type name and the trigger's name. Rename a trigger or move a class to another namespace, and its transitions can no longer find their port. The editor lists them under Invalid transitions instead of dropping them silently, so you can reconnect them. See Validation.