KzDialogue is a modular, data-driven dialogue and subtitles system for Unreal Engine 5. It is built around a clean separation between data, playback engine, and presentation, so that lines, audio, subtitles, cinematics, and gameplay events can all be driven from the same authored asset.
It ships with a custom asset editor, a Sequencer track for cinematic dialogue, and an example UMG subtitle widget. The runtime is presentation-agnostic: you can swap or stack views (subtitles, history log, 3D worldspace billboards, accessibility captions) on top of the same player.
Repository: https://github.com/kirzo/KzGameplay
⚠️ Dependencies & Installation
This plugin relies on the following custom module to function:
- KzLib: Core math and utility libraries.
Installation Steps
-
Navigate to your Unreal Engine project's root directory.
-
If it doesn't exist, create a folder named
Plugins. -
Clone or download this repository and its dependencies into the
Pluginsfolder. Your directory structure should look like this:YourProject/ └── Plugins/ ├── KzDialogue/ └── KzLib/ -
Right-click your project's
.uprojectfile and select Generate Visual Studio project files (or your IDE's equivalent). -
Open your IDE and compile the project, or simply launch the
.uprojectfile to let Unreal Engine build the missing modules. -
Ensure the plugins are enabled in your project via Edit → Plugins.
🌟 Core Systems
🗂️ Authoring (UKzDialogueAsset)
A UPrimaryDataAsset describing a dialogue as an ordered list of lines. Each line carries:
- Speaker: a
FGameplayTagidentity plus an optional display name override. - Localizable text (
FText) and an optionalUSoundBaseaudio clip. - Explicit duration, with fallback to the audio length and finally to a default.
- Tags (
FGameplayTagContainer) for mood, intent, channel hints, etc. - Audio params (
FInstancedPropertyBag) forwarded to the spawnedUAudioComponent(bool, int, float, name, object, sound wave). - Actions (
UKzDialogueAction,Instanced) that fire on line start/end without coupling the core to specific gameplay code.
Each line has a stable FGuid ID, automatically generated and preserved across edits and duplications, so external references (Sequencer sections, save data) survive reorders.
🎙️ Providers
UKzDialogueProvider is the abstract source of lines consumed by the player. Two implementations ship out of the box:
UKzAssetDialogueProvider: linear playback of aUKzDialogueAsset, with optional start/end line clamps.UKzManualDialogueProvider: ad-hoc single line, ideal for system messages and barks.
The contract supports branching (GetChoices / SelectChoice) for future graph-based providers.
🎬 Player (UKzDialoguePlayer)
The engine of the system: a non-widget UObject with an explicit state machine (Idle → Entering → LineEntering → LinePlaying → LineExiting → Exiting), audio management, line timing, and a clean event API.
- Inversion of control: views drive their own animations and notify the player when ready (
NotifyEnterFinished,NotifyLineEnterFinished, ...). Views without animations skip those phases automatically. - Commands:
Play,Pause,Resume,Stop,Abort,Interrupt,Skip. - Multicast events:
OnDialogueStarted/Finished,OnLineStarted/Finished,OnPaused/Resumed, plus per-phase view request events.
🎚️ Subsystem & Channels (UKzDialogueSubsystem)
A UWorldSubsystem that owns one player per channel (Dialogue.Main, Dialogue.Bark, Dialogue.System, ...) and arbitrates between requests using priority. Lower-priority dialogues are interrupted cleanly by higher-priority ones; equal-priority requests preempt the current one.
USub->PlayAsset(MyAsset, ChannelTag);
USub->PlayLine(MyLine, ChannelTag, /*Priority=*/10);
USub->StopChannel(ChannelTag);
🗣️ Speaker Component (UKzDialogueSpeakerComponent)
Attach to any actor that can speak. Provides:
- A
SpeakerTagandDisplayNamequeried at runtime. Speak(Asset)/SpeakLine(Line)helpers that route through the subsystem on the speaker's default channel.- A per-world registry so other systems can resolve a speaker actor from its tag.
💬 Subtitle Widget (UKzSubtitleWidget)
A reference UMG view: binds to a UKzDialoguePlayer, renders its events as fade-in/out widget animations, and updates speaker/text labels. Auto-detects whether the player should wait for fade animations based on which BindWidgetAnim slots are populated, so simple widgets without animations work out of the box.
🎞️ Sequencer Integration
A native-feeling Sequencer track for cinematic dialogue:
UMovieSceneKzDialogueTrack: holds a reference to aUKzDialogueAssetand a target channel.UMovieSceneKzDialogueSection: each section plays one specific line, identified by its stableFGuid(so asset edits don't silently break references).- Searchable line picker with filters by speaker, gameplay tags, and an option to hide lines already used in the track.
- Display name automatically extends to
Kz Dialogue (AssetName)when an asset is bound. bSuppressAudioflag for cinematics that play their own audio track.
📚 Quick Start
Play a dialogue from gameplay
UKzDialogueFunctionLibrary::PlayDialogueAsset(this, MyDialogueAsset, ChannelTag);
Bark a single line from an NPC
UKzDialogueSpeakerComponent* Speaker = ...;
FKzDialogueLine BarkLine;
BarkLine.Text = FText::FromString(TEXT("I heard something."));
Speaker->SpeakLine(BarkLine);
Bind a subtitle widget to a channel
UKzSubtitleWidget* Widget = CreateWidget<UKzSubtitleWidget>(PlayerController, SubtitleWidgetClass);
Widget->AddToViewport();
UKzDialoguePlayer* Player = GetWorld()->GetSubsystem<UKzDialogueSubsystem>()->GetOrCreatePlayer(ChannelTag);
Widget->BindPlayer(Player);
Drive dialogue from a Sequencer cinematic
- Add a Kz Dialogue track to your Level Sequence.
- Set its
DialogueAssetandChannelin the details panel. - Click + Section on the track and pick a line from the searchable menu.
- Resize the section to control on-screen duration.
🧩 Extension Points
- Custom views: subclass
UKzSubtitleWidgetor write a brand-new one — the player's event API doesn't care what the view is. Multiple views can listen to the same player. - Custom providers: subclass
UKzDialogueProviderfor branching graphs, runtime-generated dialogue, or middleware adapters (Wwise/FMOD). - Line actions: subclass
UKzDialogueActionto attach gameplay side effects to lines (camera focus, VFX, GAS effects, quest progression) without polluting the core.
License
Released under the MIT License.