Quick Start
This guide will get you from a finished StoryFlow Editor project to a working in-game dialogue system in just a few minutes. Each step builds on the last, so follow them in order.
Prerequisites
Make sure you have the StoryFlow plugin installed in your Unreal Engine project before continuing. See the Installation guide if you haven't done this yet. You will also need a StoryFlow Editor project with at least one script file.
1. Export Your Project
Before you can use your story in Unreal Engine, you need to export it from the StoryFlow Editor as a JSON build.
- Open your project in StoryFlow Editor
- Go to File > Export > JSON Export
- Choose a destination folder and click Export
The exporter creates a build directory at your chosen location with the following structure:
- project.json — Project metadata including name, language, characters, and a manifest of all scripts
- scripts/ — One
.jsonfile per script containing nodes, edges, and variables - media/ — Any images and audio files referenced by your project (textures, sound effects, etc.)
Keep the build directory intact
The importer reads all files relative to the build directory root. Do not rename or rearrange the exported files — pass the entire build directory path to the importer and it will handle the rest.
2. Import into Unreal
There are two ways to import your exported project into Unreal Engine, depending on whether you prefer Blueprint or C++.
Option A: Blueprint Library
Call the static function ImportProject from UStoryFlowImporter. This is the easiest approach and works from any Blueprint graph.
// BuildDirectory: absolute path to the exported build folder
// ContentPath: where assets will be created in your Content Browser (optional)
UStoryFlowImporter::ImportProject(
TEXT("C:/MyGame/StoryFlowExport/build"),
TEXT("/Game/StoryFlow") // defaults to "/Game/StoryFlow" if omitted
);
The ContentPath parameter controls where the imported assets are placed inside your Unreal project's Content directory. If you omit it or pass an empty string, assets are created under /Game/StoryFlow by default.
Option B: Editor Subsystem
If you prefer to use the Editor Subsystem (useful for custom editor tools or automation), you can call ImportProject directly:
UStoryFlowEditorSubsystem* Subsystem =
GEditor->GetEditorSubsystem<UStoryFlowEditorSubsystem>();
Subsystem->ImportProject(TEXT("C:/MyGame/StoryFlowExport/build")); What Gets Created
After import, the following assets appear in your Content Browser:
- SF_Project (
UStoryFlowProjectAsset) — The root project asset containing metadata and references to all scripts and characters - One
UStoryFlowScriptAssetper script — Each script file from your StoryFlow Editor project becomes its own asset - One
UStoryFlowCharacterAssetper character — Character definitions including name and portrait reference - Media assets — Images are imported as
UTexture2Dand audio files asUSoundWave
Audio format note
For best results, export audio from StoryFlow Editor in WAV format. MP3 files are imported as FileMediaSource rather than USoundWave, which limits playback options. WAV files import directly as USoundWave and work with all Unreal audio APIs.
3. Add the Component
The UStoryFlowComponent is the runtime that drives dialogue execution. Add it to any actor that needs to run a StoryFlow script — typically your player character, a dialogue manager actor, or an NPC.
- Select your actor in the level or open its Blueprint
- Click Add Component and search for "StoryFlow"
- Add the StoryFlow Component
In the Details panel, configure these properties:
- Script — Select which script to run from the dropdown. This list is populated by
GetAvailableScriptsand shows all scripts in the project asset. - LanguageCode — The language to use for dialogue text. Defaults to
"en". Set this to match the language code used in your StoryFlow Editor project.
You can also set these in C++:
// In your actor's constructor or BeginPlay
UStoryFlowComponent* StoryFlow = CreateDefaultSubobject<UStoryFlowComponent>(TEXT("StoryFlow"));
// Or find it on an existing actor
UStoryFlowComponent* StoryFlow = Actor->FindComponentByClass<UStoryFlowComponent>(); 4. Create a Basic UI
You need a UMG widget to display dialogue text and options to the player. The plugin provides two approaches:
Option A: Extend the Built-in Widget (Recommended)
Create a new Widget Blueprint that extends UStoryFlowDialogueWidget. This base class provides built-in hooks for dialogue updates so you only need to design the visual layout.
- In the Content Browser, right-click and choose User Interface > Widget Blueprint
- When prompted for a parent class, search for and select StoryFlowDialogueWidget
- Design your dialogue UI — add text blocks for the speaker name, dialogue text, and a vertical box for option buttons
- On your
UStoryFlowComponent, set the DialogueWidgetClass property to your new widget
When dialogue starts, the component automatically creates an instance of your widget and adds it to the viewport. When dialogue ends, the widget is removed.
Option B: Manual Delegate Binding
For full control, skip the widget class and bind directly to the component's delegates:
// Bind to the OnDialogueUpdated delegate
StoryFlowComponent->OnDialogueUpdated.AddDynamic(
this, &AMyActor::HandleDialogueUpdated);
// Your handler receives the current dialogue state
void AMyActor::HandleDialogueUpdated(const FStoryFlowDialogueState& State)
{
// Update your custom UI here
MyWidget->SetDialogueText(State.Text);
MyWidget->SetSpeakerName(State.Character.Name);
} Which approach should I use?
Use Option A if you want the fastest path to a working dialogue UI — the widget lifecycle is managed for you automatically. Use Option B if you need to integrate dialogue into an existing HUD or have custom widget management requirements.
5. Bind and Display
Whether you use the built-in widget or a manual binding, you read dialogue data from the FStoryFlowDialogueState struct. Here are the fields you will work with:
- Title (
FString) — The dialogue node's title, typically used as a header or scene label - Text (
FString) — The main dialogue text, already interpolated with any variable values - Character (
FStoryFlowCharacterData) — The speaking character, containing:Name(FString) — The character's display nameImage(UTexture2D*) — The character's portrait texture (may be null)
- Options (
TArray<FStoryFlowDialogueOption>) — The available choices, each containing:Id(FString) — Unique identifier to pass back when the player selects this optionText(FString) — The display text for the option button
- bCanAdvance (
bool) — Whether the dialogue can advance without selecting an option (narrative-only nodes)
Here is a complete example of populating a dialogue widget:
void UMyDialogueWidget::UpdateDialogue(const FStoryFlowDialogueState& State)
{
// Display character info
if (SpeakerNameText)
{
SpeakerNameText->SetText(FText::FromString(State.Character.Name));
}
if (CharacterPortrait && State.Character.Image)
{
CharacterPortrait->SetBrushFromTexture(State.Character.Image);
CharacterPortrait->SetVisibility(ESlateVisibility::Visible);
}
// Display dialogue text
if (DialogueText)
{
DialogueText->SetText(FText::FromString(State.Text));
}
// Build option buttons
if (OptionsContainer)
{
OptionsContainer->ClearChildren();
for (const FStoryFlowDialogueOption& Option : State.Options)
{
UButton* Button = CreateOptionButton(Option.Text, Option.Id);
OptionsContainer->AddChild(Button);
}
}
// Show a "Continue" prompt for narrative-only nodes
if (ContinueButton)
{
bool bShowContinue = State.bCanAdvance && State.Options.Num() == 0;
ContinueButton->SetVisibility(
bShowContinue ? ESlateVisibility::Visible : ESlateVisibility::Collapsed);
}
} 6. Handle Input
When the player interacts with your dialogue UI, you need to tell the StoryFlow component what happened. There are two functions to call depending on the situation:
Selecting a Choice
When the player clicks an option button, call SelectOption with the option's Id:
// Called when the player clicks an option button
void UMyDialogueWidget::OnOptionClicked(const FString& OptionId)
{
UStoryFlowComponent* StoryFlow =
GetOwningPlayerPawn()->FindComponentByClass<UStoryFlowComponent>();
if (StoryFlow)
{
StoryFlow->SelectOption(OptionId);
}
} Advancing Narrative Nodes
Some dialogue nodes have no options — they are purely narrative text that the player reads and then continues. When bCanAdvance is true and Options is empty, call AdvanceDialogue:
// Called when the player clicks "Continue" or presses a key
void UMyDialogueWidget::OnContinueClicked()
{
UStoryFlowComponent* StoryFlow =
GetOwningPlayerPawn()->FindComponentByClass<UStoryFlowComponent>();
if (StoryFlow)
{
StoryFlow->AdvanceDialogue();
}
} Input tip
You can bind AdvanceDialogue to any input action — a key press, mouse click, or gamepad button. This lets players advance through narrative sections at their own pace.
7. Run It
Everything is wired up. Now start the dialogue by calling StartDialogue on the component:
// Start the dialogue (e.g., when the player interacts with an NPC)
StoryFlowComponent->StartDialogue(); The component fires events in this order as the script executes:
- OnDialogueStarted — Fired once when
StartDialogueis called. Use this to show your dialogue UI, pause gameplay, or set up camera angles. - OnDialogueUpdated — Fired each time the runtime reaches a dialogue node. The
FStoryFlowDialogueStateparameter contains all the data you need to update your UI. - OnDialogueEnded — Fired when the script reaches an End node. Use this to hide your dialogue UI, resume gameplay, and clean up any dialogue-related state.
Here is a complete example of binding all three events:
void AMyNPC::BeginPlay()
{
Super::BeginPlay();
UStoryFlowComponent* StoryFlow = FindComponentByClass<UStoryFlowComponent>();
if (!StoryFlow) return;
StoryFlow->OnDialogueStarted.AddDynamic(this, &AMyNPC::OnDialogueStarted);
StoryFlow->OnDialogueUpdated.AddDynamic(this, &AMyNPC::OnDialogueUpdated);
StoryFlow->OnDialogueEnded.AddDynamic(this, &AMyNPC::OnDialogueEnded);
}
void AMyNPC::OnDialogueStarted()
{
// Show dialogue UI, disable player movement, etc.
UE_LOG(LogTemp, Log, TEXT("Dialogue started"));
}
void AMyNPC::OnDialogueUpdated(const FStoryFlowDialogueState& State)
{
// Update the dialogue widget with new state
if (DialogueWidget)
{
DialogueWidget->UpdateDialogue(State);
}
}
void AMyNPC::OnDialogueEnded()
{
// Hide dialogue UI, re-enable player movement, etc.
UE_LOG(LogTemp, Log, TEXT("Dialogue ended"));
} You're up and running!
You now have a complete dialogue system in Unreal Engine powered by StoryFlow. Edit your scripts in the StoryFlow Editor, re-export, re-import, and your in-game dialogue updates automatically.
Next Steps
Explore all component properties, delegates, and runtime configuration options in detail.
Learn about dialogue state, variable interpolation, and building polished UMG widgets.
Handle player selections, input options, and conditional choices in your dialogue UI.
Work with character data, portraits, and character-specific styling in your game.