Joshua Weinberg's profile

Dialogue Box (Unreal Engine UI Exercise)

Talking the Talk

To learn more about Common UI, the latest expansion to the user interface tools in Unreal Engine, the goal of this project was to design and implement a dialogue interaction with a static non-player character.

This UI solution is platform-agnostic and displays dialogue with rich formatting in a clean & friendly layout. Aside from data management asset classes, the project was built using only Blueprints and Widgets.

The Jammo character model is open source. Created by Curiomatic and Mix And Jam.
Complete flow of interaction.
Setting Up

To get dialogue up on screen, I first had to consider what occurs when players enter the level. The game mode creates the HUD for the player controller once, at the beginning of play. This HUD includes the DialogueBox Widget, albeit deactivated and therefore hidden from view.

For the rest of the session, the game will not explicitly create any more new widgets, only toggle their appearance through activation and deactivation. This is a core feature of Common UI and made on/off management much more straightforward—everything could communicate through interfaces and avoid hard references by using these generic events.
Saying Hello

Of course, there is one other widget host at play in this project: players need to know if the NPC is willing to talk, and how to take them up on the offer.

The Action Prompt widget is created as part of the NPC Blueprint, and is anchored above the NPC character model. It also begins its life hidden, until the player enters the action zone—the collision area in front of the NPC where interaction becomes possible.

To display the most accurate prompt, the UI has to detect the kind of input device players are using (in this case mouse+keyboard or gamepad), and update accordingly in real-time. I utilized the Common UI input framework to create input action types, and bind keys/buttons (along with their associated icons) to those actions.

This info is defined at the project level, so none of the individual actors or widgets need bespoke logic to see if devices have changed. If the game session ever detects a change in device, it will update any part of the UI tied to the input framework to reflect that change.

In this case, the icon beside the prompt will update according to the device currently in use.
Action Prompt, with dynamic input device detection. I switch between using the mouse and the right thumbstick to control the player camera, which triggers the game to update the prompt. I also designed the input icons.
Papers Please

The NPC would be quite the silent type without some info and dialogue to go with them. I defined a Data Asset class in C++ to contain the variables that an NPC will need.

In earlier experiments making dialogue systems, I stored these variables in the NPC Blueprint, and exposed them to be instance editable. However, that style of workflow primarily benefits artists who are changing attributes of placed actors in a level. I wanted to create a flow this time that would help developers like programmers, writers, and localizers better manage NPC data without loading a map.

The dialogue itself is stored in a data table. It implements markup tags for rich text formatting, and denoting where to create pauses in between writing text to the screen. This table in theory would grow to include all possible conversations (identified via Conv ID) for this NPC.
NPC Data Asset.
NPC Dialogue Table.
There's a 2nd conversation that will happen after you interact once. This one demonstrates a slow text speed.
UI Design

To make design iteration efficient, I defined common styles that are shared between the Action Prompt and the Dialogue Box. Aside from the rich text, all text elements behave the same way, with shared font styles. For example, the outlined display text is a single style being referenced in the prompt and as the style for the NPC's name. The dark pattern border uses a custom material, and a single instance of that is plugged into a Common Border Style.

The goal was to create a clean visual language that allowed text highlights and important elements to really pop with bold colors, for the purpose of showcasing a clear and understandable prototype that would improve and expand throughout development.
Action Prompt Widget. Uses Common Border Style and Common Text Style.
Dialogue Box Widget. Uses Common Border Style, Common Text Style, and a rich text style data table.
Border material (used to define the Common Border Style and Next Line icon). I sourced the rounded rectangle logic from this tutorial. In the future, I would like to learn how to integrate materials with Unreal Engine 5's native rounded rectangle draw mode.
World Aligned Pattern material function. Modified from the engine WorldAlignedTexture function.
Input Icons (Key E & Gamepad Face Button Right)
UI Style Utility

I created two different dialogue box experiences, along with the main one showcased so far, to demonstrate the usability of the design workflow in this project. By creating new modified instances of the border material and rich text format table, I defined new styles that could be easily swapped where they apply inside of the dialogue box widget.
The Dialogue Box style variations (main, Super Mario 3D World inspired, and Pikmin 3 inspired).
Video showcase of all three styles in action (conversation 1 in full).
Dialogue System

Though the primary goal of this project was to create a UI concept, it wouldn't get the complete point across without seeing the dialogue implementation in action!

The Dialogue Blueprint Component takes a single line from the NPC's dialogue data, and processes that text until it is ready to be fed, character-by-character, to the dialogue box's rich text block in a typewriter-style loop. It will continue to take new lines until there are no more associated with the active conversation ID, at which point the dialogue will close.

I added several quality-of-life solutions to improve the experience of both writing and playing, and to keep things from breaking, to ensure a smooth prototype experience:

• Auto adds closing tags to formatting (writers need only specify the format <Like This> before the desired bit of text)

• The complete, format-corrected line is stored separately before entering the loop, so players can hit the Action button again to skip said loop and display the completed line immediately

• The typewriter loop, and the function to inject pauses in the loop, are timer-based. They can be paused or invalidated at any time

• The sound associated with the loop will not play if it detects certain characters (spaces, closing punctuation, and certain other marks). In effect, NPCs only "speak" the letters of actual words.

• Player input is locked until necessary. The Action button will only register if dialogue is being typed or ready to move to the next line, and they cannot move their character until dialogue is over.
Skipping dialogue typewriter loops. Get to the end already, Jammo!
Conclusion

With the goal of learning about Common UI, I created this dialogue box interaction, as it incorporated widget blueprint management and designing around player input.

If I were to revisit this project, I would move the handling of all player input into the widget hierarchy while dialogue is active. This would allow for more unique experiences by freeing up input options, and taking advantage of stacking widget priority, without worrying about inputs clashing with how they would be interpreted by the player character controller.

Additionally, I would love to add character portraits and/or model state changes, and camera cuts to the UI and system! I think this style of locked-in-place dialogue opens the door to having a ton of fun with what is happening on screen.

Thank you for taking the time to check out this project breakdown!
Dialogue Box (Unreal Engine UI Exercise)
Published:

Dialogue Box (Unreal Engine UI Exercise)

Published: