StoryFlow Component
The StoryFlow Component is the core MonoBehaviour that drives dialogue execution in your Unity project. It manages the runtime, processes node graphs, and fires events your UI can respond to.
Overview
StoryFlowComponent is a MonoBehaviour that you attach to any GameObject in your scene - an NPC, a trigger volume, a game manager, or any other object that needs to run dialogue. It is marked with [DisallowMultipleComponent], so each GameObject can have at most one instance.
Internally, the component manages a StoryFlowExecutionContext that walks the node graph, handles the call stack, processes script transitions, and produces dialogue state. You do not interact with the execution context directly. The component exposes a clean C# API for starting dialogue, selecting options, reading variables, and listening to events.
One Component Per Dialogue
Each StoryFlowComponent runs one dialogue at a time. If you need multiple concurrent dialogues (for example, an NPC conversation and a tutorial prompt), use separate components on separate GameObjects. All components share global state through the StoryFlowManager singleton.
Adding the Component
There are two ways to add the component to a GameObject:
- In the Inspector, click Add Component and search for "StoryFlow Component" (listed under StoryFlow).
- In code, call
AddComponent<StoryFlowComponent>()on any GameObject.
using StoryFlow;
// Add the component to an NPC at runtime
var storyFlow = npcObject.AddComponent<StoryFlowComponent>();
storyFlow.Script = elderScript; // assign a StoryFlowScriptAsset reference
// Or reference it from a serialized field
[SerializeField] private StoryFlowComponent storyFlowComponent; Configuration Properties
All configuration properties are exposed in the Inspector. They are also accessible from C# scripts as public fields.
General Settings
Script StoryFlowScriptAsset Reference to the script asset to run when StartDialogue() is called with no arguments. Drag a StoryFlowScriptAsset from your project into this field. If left empty, the project's startup script is used as a fallback.
LanguageCode string default: "en" The language code used for string table lookup. Determines which localized text is displayed in dialogue. Currently, the StoryFlow Editor only supports English ("en"). Multi-language localization is planned for a future release.
DialogueUI StoryFlowDialogueUI optional Optional reference to a dialogue UI handler. If set, the component automatically binds to the UI when dialogue starts, calling its OnDialogueStarted, HandleDialogueUpdated, OnDialogueEnded, OnVariableChanged, and OnBackgroundImageChanged methods. If left empty, a built-in fallback UI is auto-created at runtime for quick prototyping. To manage your own UI entirely via C# events, subscribe to the component's events directly.
Audio Settings
These properties control how dialogue audio is played. They appear under the Audio header in the Inspector.
StopAudioOnDialogueEnd bool default: true When enabled, any playing dialogue audio is stopped when the dialogue session ends. Disable this if you want audio to continue playing after the conversation finishes (for example, ambient music triggered by dialogue).
DialogueAudioMixerGroup AudioMixerGroup Assigns all dialogue audio to a specific mixer group. Use this to control volume through your game's audio mixer (for example, a "Dialogue" or "Voice" group).
DialogueVolumeMultiplier float default: 1.0, range: 0-2 Volume multiplier applied to all dialogue audio. Clamped between 0 and 2. Useful for per-component volume adjustments without changing the mixer group settings.
Events
The component provides two categories of events: C# events (Action-based, for code subscribers) and UnityEvents (Inspector-assignable, for designer workflows). Both fire at the same time.
C# Events (Action-based):
| Event | Signature | Description |
|---|---|---|
OnDialogueStarted | Action | Fired when dialogue execution begins. Use this to show your dialogue UI, disable player movement, or enter a dialogue camera mode. |
OnDialogueUpdated | Action<StoryFlowDialogueState> | The primary UI update event. Fired every time the dialogue state changes - new text, new options, character change, or variable interpolation update. |
OnDialogueEnded | Action | Fired when dialogue execution completes (reaching an End node or calling StopDialogue). Use this to hide your UI and re-enable player input. |
OnVariableChanged | Action<StoryFlowVariable, bool> | Fired when a variable is modified during execution. The second parameter indicates whether the variable is global (true) or local (false). |
OnScriptStarted | Action<string> | Fired when execution enters a new script via a runScript node. Parameter is the script path. |
OnScriptEnded | Action<string> | Fired when execution returns from a script. Parameter is the script path that just finished. |
OnError | Action<string> | Fired when the runtime encounters an error (missing script, invalid node connection, stack overflow). Use for logging or error feedback during development. |
OnBackgroundImageChanged | Action<Sprite> | Fired when a setBackgroundImage node executes. Parameter is the new background sprite. |
OnAudioPlayRequested | Action<AudioClip, bool> | Fired when a playAudio node executes. Parameters are the audio clip and whether it should loop. Use this if you want to handle audio playback yourself. |
UnityEvents (Inspector-assignable):
| Event | Type | Description |
|---|---|---|
OnDialogueStartedEvent | UnityEvent | Inspector-assignable version of OnDialogueStarted. Wire up callbacks in the Inspector without writing code. |
OnDialogueUpdatedEvent | UnityEvent<StoryFlowDialogueState> | Inspector-assignable version of OnDialogueUpdated. Receives the full dialogue state. |
OnDialogueEndedEvent | UnityEvent | Inspector-assignable version of OnDialogueEnded. |
OnDialogueUpdated is Your Main Hook
In most projects, OnDialogueUpdated is the only event you need to build a complete dialogue UI. It fires whenever the dialogue state changes and provides the full StoryFlowDialogueState including text, character, options, images, and audio. See Displaying Dialogue for details on the state class.
Subscribing in C#:
using StoryFlow;
using StoryFlow.Data;
public class NPCDialogue : MonoBehaviour
{
[SerializeField] private StoryFlowComponent storyFlow;
private void OnEnable()
{
storyFlow.OnDialogueStarted += HandleDialogueStarted;
storyFlow.OnDialogueUpdated += HandleDialogueUpdated;
storyFlow.OnDialogueEnded += HandleDialogueEnded;
}
private void OnDisable()
{
storyFlow.OnDialogueStarted -= HandleDialogueStarted;
storyFlow.OnDialogueUpdated -= HandleDialogueUpdated;
storyFlow.OnDialogueEnded -= HandleDialogueEnded;
}
private void HandleDialogueStarted()
{
// Show your dialogue UI
}
private void HandleDialogueUpdated(StoryFlowDialogueState state)
{
// Update your UI with the new dialogue state
}
private void HandleDialogueEnded()
{
// Hide your dialogue UI, re-enable player input
}
} Control Methods
These public methods control the dialogue flow. Call them from your input handlers, UI buttons, or game logic scripts.
| Method | Parameters | Description |
|---|---|---|
StartDialogue() | None | Begins dialogue using the configured Script asset. Falls back to the project's startup script if Script is not assigned. |
StartDialogue(string) | string scriptPath | Begins dialogue with the specified script path, overriding the component's Script property. |
StartDialogue(StoryFlowScriptAsset) | StoryFlowScriptAsset script | Begins dialogue with a direct asset reference. Useful for avoiding path lookups. |
SelectOption(string) | string optionId | Selects a dialogue option by its ID. The ID comes from StoryFlowOption.Id in the current dialogue state. |
AdvanceDialogue() | None | Advances the dialogue when the current node has no options. Equivalent to the player clicking "continue". |
StopDialogue() | None | Immediately stops dialogue execution and fires OnDialogueEnded. |
PauseDialogue() | None | Pauses dialogue execution. The dialogue state is preserved until resumed. |
ResumeDialogue() | None | Resumes a paused dialogue from exactly where it left off. |
PauseExecution() | None | Pauses node execution after the current node completes. The next node is held until ResumeExecution() is called. |
ResumeExecution() | None | Resumes execution from a PauseExecution() hold. |
PauseExecutionFor(float) | float seconds | Pauses execution for the given duration, then resumes automatically. Returns a Coroutine you can track or stop. |
InputChanged(string, string) | string optionId, string value | Submits a typed input value change for an input option. Stores the value, re-interpolates dialogue text, broadcasts OnDialogueUpdated, and optionally follows an "on change" edge. |
InputChanged(string, StoryFlowVariant) | string optionId, StoryFlowVariant value | Typed overload of InputChanged that accepts a StoryFlowVariant directly. |
// Player interacts with NPC
public void OnInteract()
{
if (!storyFlowComponent.IsDialogueActive())
{
storyFlowComponent.StartDialogue();
}
}
// Player presses "Continue" key
public void OnContinuePressed()
{
if (storyFlowComponent.IsDialogueActive()
&& storyFlowComponent.IsWaitingForInput())
{
storyFlowComponent.AdvanceDialogue();
}
}
// UI button calls this when the player picks an option
public void OnOptionSelected(string optionId)
{
storyFlowComponent.SelectOption(optionId);
} State Access
These methods let you query the current state of the dialogue without modifying it. They are safe to call from UI update logic, animation controllers, or any read-only context.
| Method | Return Type | Description |
|---|---|---|
GetCurrentDialogue() | StoryFlowDialogueState | Returns the current dialogue state. May return null if no dialogue is active. |
IsDialogueActive() | bool | Returns true if a dialogue is currently running. Useful for input gating and UI visibility checks. |
IsWaitingForInput() | bool | Returns true if the dialogue is waiting for the player to select an option or advance. |
IsPaused() | bool | Returns true if the dialogue is currently paused via PauseDialogue(). |
GetProject() | StoryFlowProjectAsset | Returns the effective project asset from StoryFlowManager.Instance.Project. |
Variable Access
These methods let you read and write StoryFlow variables from game code. Each variable type has its own getter and setter pair. All lookups are by display name (the name shown in the StoryFlow Editor), not by internal ID.
| Method | Parameters | Return Type |
|---|---|---|
GetBoolVariable | string name, bool global = false | bool |
SetBoolVariable | string name, bool value, bool global = false | void |
GetIntVariable | string name, bool global = false | int |
SetIntVariable | string name, int value, bool global = false | void |
GetFloatVariable | string name, bool global = false | float |
SetFloatVariable | string name, float value, bool global = false | void |
GetStringVariable | string name, bool global = false | string |
SetStringVariable | string name, string value, bool global = false | void |
GetEnumVariable | string name, bool global = false | string |
SetEnumVariable | string name, string value, bool global = false | void |
GetCharacterVariable | string charPath, string varName | StoryFlowVariant |
SetCharacterVariable | string charPath, string varName, StoryFlowVariant value | void |
ResetVariables | None | void |
The global Parameter
The global parameter (default false) determines search scope. When false, the getter searches local script variables first, then falls back to global. When true, only global variables are searched. If a variable is defined as global in the StoryFlow Editor, pass global: true to target it directly.
// Check if the player has completed a quest (global variable)
bool questDone = storyFlowComponent.GetBoolVariable("mainQuestCompleted", global: true);
// Give the player gold (local script variable)
int currentGold = storyFlowComponent.GetIntVariable("gold");
storyFlowComponent.SetIntVariable("gold", currentGold + 100);
// Set a character-specific variable
storyFlowComponent.SetCharacterVariable(
"characters/elder",
"trustLevel",
StoryFlowVariant.Int(5)
);
// Reset all local variables to their default values
storyFlowComponent.ResetVariables(); ResetVariables Scope
ResetVariables() only resets local script variables to their default values. Global variables are not affected. To reset global variables, call StoryFlowManager.Instance.ResetGlobalVariables().
Lifecycle
The component follows a straightforward lifecycle tied to Unity's MonoBehaviour callbacks:
- StartDialogue() - When you call
StartDialogue(), the component retrieves a reference toStoryFlowManager.Instance, initializes its execution context with the shared state (global variables, runtime characters, once-only option tracking), and auto-binds to theDialogueUIif one is assigned. It subscribes the UI toOnDialogueStarted,OnDialogueUpdated,OnDialogueEnded,OnVariableChanged, andOnBackgroundImageChanged. It then walks the node graph, fires events, and waits for player input. You can pause, resume, or stop at any time. - OnDisable - If a dialogue is active, it is stopped cleanly, firing
OnDialogueEnded. - OnDestroy - Stops any active dialogue and nullifies all C# event subscribers to prevent memory leaks from dangling references.
// Simplified lifecycle overview
private void OnDisable()
{
if (isDialogueActive)
StopDialogue();
}
private void OnDestroy()
{
if (isDialogueActive)
StopDialogue();
// Clear all C# event subscribers to prevent memory leaks
OnDialogueStarted = null;
OnDialogueUpdated = null;
OnDialogueEnded = null;
OnVariableChanged = null;
OnError = null;
OnAudioPlayRequested = null;
OnBackgroundImageChanged = null;
OnScriptStarted = null;
OnScriptEnded = null;
} Relationship with StoryFlowManager
StoryFlowManager is a singleton MonoBehaviour that persists across scene loads via DontDestroyOnLoad. It acts as the central authority for shared state, while each StoryFlowComponent operates as an independent dialogue runner. The manager auto-creates itself at runtime when first needed - you do not need to manually add it to your scene. It automatically discovers the project asset in your project.
What the manager handles:
- Global Variables - A single global variable store shared by all components. When one component's dialogue sets a global variable, every other component sees the updated value immediately.
- Runtime Characters - Deep copies of character data loaded from the project asset. Character variables modified during gameplay are shared across all components.
- Once-Only Options - Tracks which "show once" dialogue options have already been selected. This tracking persists across different components and script files within the same session.
- Project Asset - Holds the imported StoryFlow project (
StoryFlowProjectAsset) with all scripts, characters, and resolved media assets. - Save/Load - Provides
SaveToSlot()andLoadFromSlot()methods that serialize and restore all shared state.
What each component manages independently:
- Local Variables - Each component has its own local variable scope for the currently executing script.
- Execution State - Call stack, current node position, and flow state are per-component.
- Audio Playback - Each component creates and manages its own
AudioSourceon demand. - Events - C# events and UnityEvents are fired per-component, so each GameObject's UI only receives updates for its own dialogue.
Multiple NPCs, Shared World
This architecture means you can have dozens of NPCs running independent dialogues while sharing the same world state. A merchant NPC can check a global mainQuestCompleted variable that was set by a quest-giver NPC's dialogue, and both share the same character relationship data - all without any manual synchronization.