A node-based dialogue system plugin for Unreal Engine 5.6+. DialogueFlow provides a visual graph editor for authoring branching conversations, a runtime component that lives on each NPC, a global subsystem for centralized control, and full localization support via Unreal's String Table pipeline.
- Features
- Installation
- Module Setup
- Core Concepts
- Node Types Reference
- Creating a Dialogue Asset
- Localization Setup
- Runtime: UDialogueComponent
- Runtime: UDialogueSubsystem
- Delegate Reference
- Blueprint Workflow
- Gameplay Tag Integration
- Camera Direction
- File Structure
- Visual graph editor — author branching dialogues as a node graph inside the Unreal editor, with auto-wiring when dragging connections
- Graph watermark — editor displays "Dialogue Flow" label in the corner for quick identification
- Five node types — Start, Entry Point, Dialogue, Action, and End.
- Comments — add freeform annotation boxes to the graph; press
Cor right-click to insert - UDialogueComponent — actor component that drives dialogue on a per-NPC basis; multiple NPCs can run independent sessions simultaneously
- UDialogueSubsystem — game-instance subsystem for centralized dialogue control when a single global session is preferred
- Proximity detection — configurable box collision on
UDialogueComponentfiresOnWithinConversationRadius/OnLeftConversationRadiuswhen the player enters/leaves NPC range - Localization — Dialogue nodes store a
DialogueKey(FName) resolved at runtime through Unreal's String Table system; automatically returns the correct translation for the active culture - Searchable combo box — the Details panel shows a searchable dropdown populated from the asset's String Table for both
DialogueKeyand responseResponseTitleproperties - Response options — each Dialogue node can carry multiple
FDialogueResponseentries with display text, a required Gameplay Tag gate, and an enabled/disabled flag - Camera direction hints —
ECameraDirectionenum on Dialogue and Action nodes lets the game layer know which cinematic framing to use (OverShoulder,CloseUp,Wide,CowboyShot,TwoShot,POV,Dutch) - Gameplay Tags — Dialogue nodes carry an
Emotiontag; Action nodes carry anActionTag; response options carry aRequiredtag for conditional availability - Speaker metadata — each Dialogue node exposes
SpeakerID,SpeakerName, and a soft reference to aUTexture2Dportrait - Audio — each Dialogue node carries a soft reference to a
USoundWavefor voiced lines - Entry Points — named jump-in nodes let you start a dialogue at any point in the graph without restarting from the beginning
- Auto-advance — Start, Entry Point, and Action nodes automatically advance to the next node; the graph only pauses at Dialogue nodes
-
Copy the
DialogueFlowfolder into your project'sPlugins/directory:YourProject/ └── Plugins/ └── DialogueFlow/ ├── DialogueFlow.uplugin └── Source/ -
Right-click your
.uprojectfile and select Generate Visual Studio project files. -
Open the project in Unreal Engine. On first load the engine will prompt you to compile the plugin — click Yes.
-
Verify the plugin is active: Edit → Plugins → Project → DialogueFlow — the checkbox should be ticked.
If your game module needs to call DialogueFlow APIs from C++, add the runtime module to your Build.cs:
// YourProject.Build.cs
PublicDependencyModuleNames.AddRange(new string[]
{
"Core", "CoreUObject", "Engine",
"DialogueFlow" // <-- add this
});The editor-only module (DialogueFlowEditor) is loaded automatically by the plugin descriptor and does not need to be listed in game module dependencies.
| Term | Description |
|---|---|
| UDialogueAsset | A UDataAsset that holds all nodes for one NPC's dialogue tree and a reference to its String Table |
| UDialogueNode | Base class for all nodes; stores a NodeGuid and OutputNodeGuids array |
| UDialogueComponent | Actor component placed on an NPC; owns one dialogue session at a time |
| UDialogueSubsystem | Game-instance subsystem; owns one global dialogue session |
| DialogueKey | An FName that maps to a row in the asset's String Table |
| Entry Point | A named node that lets you jump into a dialogue graph mid-flow |
Both UDialogueComponent and UDialogueSubsystem expose the same logical API (StartDialogue, AdvanceDialogue, EndDialogue) and the same set of delegates. Choose whichever fits your architecture:
- UDialogueComponent — preferred when each NPC owns its conversation state (multiple simultaneous conversations are possible)
- UDialogueSubsystem — preferred when only one conversation can be active at a time and you want a single place to bind UI delegates
The entry node automatically placed when a UDialogueAsset is created. Every asset has exactly one. Execution always begins here when you call StartDialogue. Automatically advances to the first connected node.
A named alternative entry that lets you call StartDialogueAtEntry(Name) to jump into the middle of a graph. Useful for branching back into a conversation after a quest update, or for replaying only a specific section.
| Property | Type | Description |
|---|---|---|
EntryPointName |
FName |
The name you pass to StartDialogueAtEntry |
The main conversational beat. Execution pauses here and fires OnDialogueNodeChanged; the game advances when AdvanceDialogue(ResponseIndex) is called.
| Property | Type | Description |
|---|---|---|
SpeakerID |
FName |
Logical identifier for the speaker (e.g. Marshal, Player) |
SpeakerName |
FName |
Display name shown in the UI |
SpeakerImage |
TSoftObjectPtr<UTexture2D> |
Portrait texture for the speaker |
Emotion |
FGameplayTag |
Emotional state tag (e.g. Emotion.Angry) |
Camera |
ECameraDirection |
Cinematic framing hint for this line |
DialogueKey |
FName |
Row key in the asset's String Table |
DialogueAudio |
TSoftObjectPtr<USoundWave> |
Voiced audio for this line |
ResponseOptions |
TArray<FDialogueResponse> |
Player response choices (see below) |
DisplayDuration |
float |
Auto-advance duration in seconds (0 = wait for input) |
| Property | Type | Description |
|---|---|---|
ResponseTitle |
FName |
String Table key for the response text shown to the player |
Required |
FGameplayTag |
Tag that must be present on the initiator to show this option |
bIsEnabled |
bool |
Whether this response can currently be selected |
A non-blocking beat that fires OnConversationAction and then immediately advances to the next node. Use it to trigger game events (play animation, give item, set variable) without interrupting dialogue flow.
| Property | Type | Description |
|---|---|---|
Title |
FName |
Human-readable label shown in the graph |
ActionTag |
FGameplayTag |
Tag identifying which action to perform |
Camera |
ECameraDirection |
Cinematic framing hint for this action |
Terminates the dialogue session and fires OnConversationEnded. Connect any branch that should close the conversation to an End node.
An annotation box that lives only in the editor graph. Press C or right-click the graph background and choose Add Comment to insert one. Comments have no runtime effect.
- In the Content Browser, right-click → Dialogue → Dialogue Asset.
- Name the asset (e.g.
DA_Marshal_Intro). - Double-click to open the Dialogue Flow graph editor.
- The graph starts with a single Start node.
- Right-click the graph background to add nodes:
- Add Dialogue Node — a conversational beat
- Add Action Node — a game-event trigger
- Add Entry Point — a named jump-in
- Add End Node — closes the conversation
- Add Comment (or press C) — annotation box
- Drag from an output pin to another node's input pin to connect them. Dragging from a pin onto the background opens a context menu pre-filtered to connectable node types.
- Select any node to edit its properties in the Details panel.
- Assign a Dialogue String Table asset in the asset's top-level Details panel (see Localization Setup).
DialogueFlow uses Unreal's built-in String Table pipeline for all dialogue text. This means translations are managed entirely through the Localization Dashboard and the text system handles culture selection automatically.
- Content Browser → right-click → Miscellaneous → String Table
- Name it (e.g.
ST_Marshal). - Open it and add rows. Each row has a Key (e.g.
MARSHAL_INTRO_01) and a Source String (the English base text).
- Open your
UDialogueAsset. - In the Details panel, set Dialogue String Table to your
ST_Marshalasset.
- Select a Dialogue node in the graph.
- The Dialogue Key property shows a searchable dropdown populated from the assigned String Table. Each entry shows the key and a preview of the source string.
- Select the appropriate key. If the key is missing from the table a warning icon appears.
Response options (ResponseTitle) use the same combo box and pull from the same String Table.
Use the Unreal Localization Dashboard (Tools → Localization Dashboard):
- Gather text from assets (this picks up your String Table source strings).
- Export
.pofiles, send to translators, import the translated.pofiles back. - The engine will automatically serve the correct translation at runtime based on
FInternationalization::Get().GetCurrentCulture().
Call GetLocalizedDialogueText on the node, passing the active UDialogueAsset:
// C++
FText Line = DialogueNode->GetLocalizedDialogueText(ActiveAsset);// Blueprint
Dialogue Node → Get Localized Dialogue Text (Asset) → Set Text (UI)
This returns the localized FText for the active culture, or falls back to the raw key name if the String Table is not assigned.
Add one UDialogueComponent to each NPC Blueprint that participates in dialogue.
- Open your NPC Blueprint.
- Add Component → Dialogue Flow Component.
- Set Default Dialogue to the NPC's
UDialogueAsset. - Bind the On Dialogue Node Changed event in the Event Graph to drive your UI.
- Call Start Dialogue from an interaction trigger (e.g. when the player presses the interact key inside the conversation radius).
- Call Advance Dialogue from your UI response buttons.
The component automatically creates a UBoxComponent child for proximity detection.
| Property | Default | Description |
|---|---|---|
ConversationRadiusExtent |
(200, 200, 100) |
Half-extent of the detection box in cm |
ConversationRadiusScale |
(1, 1, 1) |
Scale multiplier applied to the box |
ConversationRadiusCollisionProfile |
Trigger |
Collision profile name |
bEnableRadiusEvents |
true |
When false, overlap events are not bound |
Bind OnWithinConversationRadius to show an interaction prompt when the player is close enough, and OnLeftConversationRadius to hide it.
| Function | Description |
|---|---|
StartDialogue(Initiator, OverrideAsset) |
Begin from the asset's Start node |
StartDialogueAtEntry(Initiator, EntryPointName, OverrideAsset) |
Begin from a named Entry Point |
AdvanceDialogue(ResponseIndex) |
Advance to the node at the given output index |
EndDialogue() |
Immediately end the session |
IsDialogueActive() |
Returns true if a session is running |
GetConversationRadiusBox() |
Returns the proximity UBoxComponent |
OverrideAsset is optional on both Start functions. If nullptr, DefaultDialogue is used.
For Dialogue nodes with only a single Next output (no response options), pass 0 to AdvanceDialogue.
UDialogueSubsystem is a UGameInstanceSubsystem — it is automatically instantiated when the game starts and lives for the duration of the game instance. Access it from Blueprint with Get Dialogue Flow Subsystem or from C++ with:
UDialogueSubsystem* DS = GetGameInstance()->GetSubsystem<UDialogueSubsystem>();| Function | Description |
|---|---|
StartDialogue(Asset, Initiator, Target) |
Begin from the asset's Start node |
StartDialogueAtEntry(Asset, Initiator, Target, EntryPointName) |
Begin from a named Entry Point |
AdvanceDialogue(ResponseIndex) |
Advance to the node at the given output index |
EndDialogue() |
Immediately end the session |
IsDialogueActive() |
Returns true if a session is running |
Unlike UDialogueComponent, the subsystem requires you to pass Target explicitly (typically the NPC actor).
| Delegate | Signature | Fired When |
|---|---|---|
OnConversationStarted |
(UDialogueAsset* Asset, AActor* Initiator, AActor* Target) |
A dialogue session begins |
OnDialogueNodeChanged |
(UDialogueNode_Dialogue* DialogueNode) |
A Dialogue node is reached |
OnConversationEnded |
(UDialogueAsset* Asset) |
The session ends (End node or EndDialogue()) |
OnConversationAction |
(UDialogueNode_Action* ActionNode) |
An Action node is reached |
OnWithinConversationRadius |
(AActor* Initiator) |
An actor enters the proximity box |
OnLeftConversationRadius |
(AActor* Initiator) |
An actor leaves the proximity box |
Target in OnConversationStarted is always GetOwner() — the NPC the component lives on.
| Delegate | Signature | Fired When |
|---|---|---|
OnConversationStarted |
(UDialogueAsset* Asset, AActor* Initiator, AActor* Target) |
A dialogue session begins |
OnDialogueNodeChanged |
(UDialogueNode_Dialogue* DialogueNode) |
A Dialogue node is reached |
OnConversationEnded |
(UDialogueAsset* Asset) |
The session ends |
OnConversationAction |
(UDialogueNode_Action* ActionNode) |
An Action node is reached |
Event BeginPlay
└── Dialogue Component → Bind On Within Conversation Radius → Show Interact Prompt
On Within Conversation Radius (Initiator)
└── [Player presses E] → Dialogue Component → Start Dialogue (Self)
On Dialogue Node Changed (DialogueNode)
├── Set Speaker Name Text ← DialogueNode → SpeakerName
├── Set Dialogue Text ← DialogueNode → Get Localized Dialogue Text (Asset)
├── Set Portrait Image ← DialogueNode → SpeakerImage
└── Build Response Buttons ← DialogueNode → ResponseOptions (loop)
└── On Button Clicked → Dialogue Component → Advance Dialogue (Index)
On Conversation Ended
└── Hide Dialogue UI
On Conversation Action (ActionNode)
└── Switch on ActionTag
├── "Action.GiveItem" → Give Item to Player
├── "Action.PlayAnim" → Play Montage
└── "Action.SetFlag" → Set Quest Flag
// In Game Mode or Player Controller BeginPlay:
Get Dialogue Flow Subsystem → Bind On Dialogue Node Changed → (same UI binding as above)
// When player interacts with NPC:
Get Dialogue Flow Subsystem → Start Dialogue (Asset, PlayerRef, NPCRef)
DialogueFlow uses Gameplay Tags in three places:
| Location | Property | Purpose |
|---|---|---|
| Dialogue Node | Emotion |
Drives animation/expression blend on the speaker |
| Action Node | ActionTag |
Identifies which game event to execute |
| FDialogueResponse | Required |
Gates a response option behind a tag on the Initiator |
To gate a response on a tag, set the Required property on the FDialogueResponse. Your UI layer should check whether the Initiator's UAbilitySystemComponent (or equivalent) owns the tag before displaying that option, or use the bIsEnabled flag to disable it visually.
ECameraDirection is a hint enum you read in your camera or cinematic system. DialogueFlow does not move the camera itself — it communicates intent through the enum so your game layer can respond.
| Value | Intended Use |
|---|---|
None |
No camera change; keep current framing |
OverShoulder |
Classic RPG over-the-shoulder shot |
CloseUp |
Face close-up for emotional moments |
Wide |
Wide establishing or reaction shot |
CowboyShot |
Mid-thigh framing (classic Western) |
TwoShot |
Both characters in frame |
POV |
First-person point of view |
Dutch |
Tilted/canted angle for tension |
Read the Camera property from the UDialogueNode_Dialogue* or UDialogueNode_Action* received in the delegate and pass it to your cinematic subsystem.
Plugins/DialogueFlow/
├── DialogueFlow.uplugin
└── Source/
├── DialogueFlow/ # Runtime module
│ ├── Public/
│ │ ├── Core/
│ │ │ └── DialogueFlow.h
│ │ ├── Nodes/
│ │ │ ├── DialogueAsset.h # UDataAsset holding nodes + String Table
│ │ │ ├── DialogueNode.h # Base node class
│ │ │ ├── DialogueNode_Conversation.h # Dialogue node (UDialogueNode_Dialogue)
│ │ │ ├── DialogueNode_Action.h # Action node
│ │ │ ├── DialogueNode_Start.h # Start node
│ │ │ ├── DialogueNode_End.h # End node
│ │ │ ├── DialogueNode_EntryPoint.h
│ │ │ ├── DialogueResponse.h # FDialogueResponse struct
│ │ │ └── DialogueCameraDirection.h # ECameraDirection enum
│ │ ├── Components/
│ │ │ └── DialogueComponent.h # Per-NPC actor component
│ │ └── Subsystems/
│ │ └── DialogueSubsystem.h # Global game-instance subsystem
│ └── Private/
│ ├── Nodes/
│ │ └── DialogueNode_Conversation.cpp
│ ├── Components/
│ │ └── DialogueComponent.cpp
│ └── Subsystems/
│ └── DialogueSubsystem.cpp
└── DialogueFlowEditor/ # Editor-only module
├── Public/
│ ├── Core/
│ │ └── DialogueFlowEditor.h
│ ├── Graph/
│ │ ├── DialogueGraph.h
│ │ ├── DialogueGraphSchema.h
│ │ ├── DialogueEdNode_*.h # Editor graph node wrappers
│ │ └── SDialogueGraphNode_*.h # Slate widget implementations
│ ├── Toolkit/
│ │ └── DialogueAssetEditorToolkit.h
│ ├── AssetActions/
│ │ ├── DialogueAssetTypeActions.h
│ │ └── DialogueAssetFactory.h
│ ├── Factory/
│ │ └── DialogueNodeFactory.h
│ ├── Customization/
│ │ ├── DialogueNodeCustomization.h # DialogueKey combo box
│ │ └── DialogueResponseCustomization.h # ResponseTitle combo box
│ └── Styling/
│ └── DialogueFlowStyle.h
└── Private/
└── ...
- Unreal Engine 5.6 or later
GameplayTagsplugin (included with Unreal Engine, enabled by default)- C++ project (the plugin contains C++ source and must be compiled)