The Problem🛑
For X-GRAVITY we knew we’d be have multiple points where narrative is delivered through dialogue, sometimes non-linear and branching.
Solution âś…
So I came to the conclusion that it’d be worthwhile building our own dialogue tool within Unreal Engine. What I ended up building was a plugin we call the Blueshift Conversation Plugin.
The plugin we built is capable of:
- Authoring non-linear, branching dialogue through nodes
- Support for reusing graphs and thus dialogue
- Event hooks for a flexible Blueprint or C++ implementation
- Extendibility through Blueprints – think making custom tasks for Behaviour Tree
- Support for between 1 and many participants in a conversation
- “Garble” style dialogue inspired by Animal Crossing
- Implementable in any Unreal Engine 5 project!

Implementation
There’s so much that can be covered here, but I’ll only focus on the important (and fun) bits!
CORE
I written the tool entirely in C++ – thank you JetBrains Rider for making such a good Unreal development environment).


I first written a top layer of plugins which extend the Asset Editor and Graph APIs to reduce the boilerplate and streamline implementation of a tool like this – this is not the first time I’d needed to write a graph-based tool, nor is it the last!
RUNTIME
The runtime component hinged around the Conversation Manager – a component which is designed to be implemented on the player, and handles managing of runtime states like which tree we’re in, how deep, which node etc.

I knew I wanted to make a high-level API which is easy to understand – so everything is event based with delegates that can be bound to, and involves passing around a Conversation Instance – some lightweight data that holds info about the conversation state.

EDITOR
Once I’d figured out the runtime API, I started building the editor API – which I won’t go into as it involves a mountain of boilerplate classes! What I came out with was an API where I can extend new nodes in C++, and I’d explicitly define hooks for Blueprints via instanced objects.

NOTE: Inline UObjects
If you didn’t know, you can inline instanced UObjects using Instanced and EditInlineNew – this gives you a dropdown to instantiate UObjects on the specified class in a field.



GARBLE & TEXT
One feature that came up was “garble” dialogue (i.e. Animal Crossing), where the dialogue is spoken out character-by-character, and random sounds play.
The solution I went with, was to be able to supply a database of sound clips mapped to characters, which would be played as each character is typed out (but only if the last clip finished playing, to prevent chaos).

But we also wanted to be able to script certain events in the dialogue, i.e. changing the speed, adding a pause, or playing an animation.
I took a page out of rich text formatting (which we also support), and implemented my own using [ ] to give us something like this..
[speed=1.3]I am {Name0}![speed=1][pause=0.2]
The best[pause=0.3], um[pause=0.3], up and coming gravboarder there is!
I parsed this into tokens and recreated the dialogue text, linking tokens to specific characters, so when the character is hit, we trigger all prior events.
This means we can pause, speed up – do whatever we want!

You also maybe noticed some text like this {Name0} – this leads me into another feature I written I called translators. These are hooked-in objects for formatting text within { } with specific data pulled from the conversation instance.
i.e. I have some translators setup globally – also if you didn’t know, you can create custom project settings by extending UDeveloperSettings!

For example here’s the code for our translator which handles names and pronouns. Another side-note – yes we use interfaces! We want the implementation to be project-agnostic, so interfaces are great here.

The Future 🚀
As a company, we’re looking to provide access to some of our internal tech stack – Unreal Engine 5 plugins, Blender tools, and more! All battle-tested on real projects. This plugin will be part of that remit.
Before that point I wanted to outline some future features and improvements I want to make:
- UX improvements, i.e. custom portraits and bigger character names on nodes to easily scan the conversation
- Behaviour Tree style decorators to replace conditionals, and make the graph feel more modular
- Switch-case nodes, animation nodes, camera nodes.. just more nodes!
Until then, your local artist turned engineer, signing off!
– Luna


Leave a Reply