Skip to content

Dialogue manual

Daniel Butum edited this page Apr 24, 2019 · 46 revisions

[[TOC]]

1. Introduction

The plugin contains a dialogue backend system with proper editor support for unreal engine. We tried to make it as general as possible, but the main design decisions were made based on the needs of our own game. The source code is public though - even if your needs are different you may find it a good starting point.

This document describes both the integration and the usage of the system, however it expects some general knowledge about the engine from the reader.

Using the plugin you will create Dialogue Assets in the content browser - they contain the static data with some logical expressions (they are similar to behavior trees, but not that complex). In those you will reference Dialogue Participants - they are objects implementing the proper interface functions.

In order to start a dialogue runtime you will need to provide an array of Dialogue Participants matching the ones referenced inside the dialogue. If the dialogue is started successfully you will get a Dialogue Context which can be used to control the dialogue and get information from its current state.

The Dialogue Memory will contain the visited nodes for each dialogue - this can be used for some of the conditions.

Both UI and serialization are outside of the scope of this plugin - we found them way too game specific to be included.

2. Creating Dialogues

Getting started

You can create a Dialogue Asset in content browser using Right Click -> Dialogue System -> Dialogue. Doing this will also create a text file in the same folder by default - it contains exactly the same data as the .uasset. You can change the format of the text file or disable it completely in the dialogue editor settings.

Create and open a Dialogue to open the graph editor.

create_dialogue

The dialogue graph is constructed from different nodes and the edges between them. Some node contains text or texts, others are only there to build up more complicated logical behavior. The edges can represent player choices or in some case they are simply there to modify the flow of the dialogue.

Just like in behavior tree, the children of a node are sorted based on the horizontal location of their visual representation: the one in the left is the first, and the one in the right is the last.

Each node has a number in the top right corner: that is the index of the node.

image_0

Node types

Start Node

Capture

Defines the entry point of the Dialogue - its children are evaluated at the beginning of the dialogue and the first successful child defines the first line of the dialogue. It does not contain any text, does not have any conditions, does not fire any event, and it is the only node without a node owner. The start node is already placed and can not be removed.

Speech Node

Capture1

A standard dialogue line - it has an owner (speaker) and a text. Optionally it can also contain a Sound Wave or a Dialogue Wave - you can select which to use (or hide both) globally in the dialogue dialogue settings.

Virtual Parent Node

The node has a bool property IsVirtualParent. If it is set the Node will list the children of its first satisfied child as its own - it is useful when you want to give the user the same player choices after different NPC lines. Virtual Parent dialogue speech nodes are displayed with gray background.

You can think of this node type as a helper/shortcut node.

Example:

  • With virtual parent node before
  • Without virtual parent node after

Speech Sequence Node

Capture2

The purpose of this node is to make the graph more organized - a single speech sequence node contains the data of multiple speech nodes and can be used instead of those in linear cases. You can extract a speech sequence node to a series of speech nodes via Right Click on the node and choosing Convert to speech nodes in the context menu. You can also convert more speech nodes into a sequence node, but only if they are connected with each other without any branches. Simply select them, right click on empty space in the grid and select Convert… from the context menu.

Selector Node

Capture3

This node type does not contain any text to display and the dialogue is not supposed to stop reaching these. When the node is entered its children are evaluated and one of them is selected immediately. Depending on the Selector Type the selected node is either the first satisfied child or a randomly picked one.

End Node

Capture4

The dialogue is terminated when the execution flow reaches an end node. This node type does not have any text attached, but it can have conditions and it can trigger events.

Edges

Each edge can contain conditions and a text. The ones coming from a Selector node are evaluated and stepped over automatically. In other cases the game can get the data from the actual outgoing edges from the current node to provide them as choices to the player.

Edges that are part of the shortest way from start node to the target node are called Primary Edges, the rest are called Secondary edges. This categorization is purely for visual clarity: they can be displayed with different colors and each category can be hidden.

Building the graph

Base operations:

Add node: right click in the grid and select the desired node type under Dialogue Node category in the context menu.

Add edge: press and hold left mouse button on the (black) border area of the source node, then drag the mouse to the border of the target node.

Retarget edge: hold Ctrl and drag the edge via left mouse button to change its target node.

The graph editor also supports undo/redo and copy/paste.

To edit a graph or an edge simply select it via left click, then you can use the details panel to change its properties.

Conditions

Edges and nodes can contain enter conditions - a node is only reachable from an edge if the conditions belonging to the edge and to the node are all satisfied.

You can add a condition in the details panel of the edge or node:

condition_example_1

If a node or edge has a condition an icon is displayed in the graph:

image_2image_3

The conditions are stored in arrays and the content of those arrays are evaluated together. The Strength of a condition can be strong or weak. A condition array is satisfied if it only contains satisfied strong conditions, and it has at least one satisfied weak condition, or none at all. In other words the condition array fails (and the node cannot be entered) if there are any failed strong conditions or all the weak conditions are failed ones (or both).

The Condition Type defines the behaviour of the condition

condition_type

Some condition asks for a variable from the owner participant and performs a logical operation on it. The supported variable types are Integer, Float, Boolean and Name. (Managing these variables are outside of the scope of the plugin, it simply uses an interface to request those values from the participants).

The Check named condition expects the participant to execute a more complicated logical expression identified by the Condition Name.

dlgcondition

The Was node already visited condition checks if the node with the given index was already visited or not.

If the Long Term Memory is checked the previous dialogues using the same Dialogue Asset are taken into account as well, otherwise the check is limited to the actual dialogue context.

Using random in any condition is not supported and can lead to undefined behavior. The dialogue system can call the conditions multiple time in an update and it expects to get the same results.

Events

dlgevent

Nodes can have enter events - these are executed each time the node is reached in the active dialogue context. Nodes with events are also marked with an icon (see image).

image_5

Similarly to Conditions, events can either modify (or set) the value of a supported variable type, or it can simply execute a named event the participant have to handle.

3. Integration and usage

Participants

To start a dialogue some of your objects (e.g. your player character class/blueprint) need to implement the DlgDialogueParticipant interface. It supports both C++ and blueprint. If you work with C++ check DlgDialogueParticipant.h. In Blueprint you will get the functions you have to implement if you added the interface to the class using the Class Settings.

dialogue_interfaces

The only function you have to implement in all case is the GetParticipantName - this should return a Name variable which has to be unique inside any Dialogue Asset - the participant is identified with this inside the Dialogue Editor.

The other functions are optional. The variable getters and the CheckCondition function are used by the conditions, the variable modifiers and the OnDialogueEvent function are used by the events. The rest (GetParticipantDisplayName, GetParticipantIcon, etc.) can be used to get those extra informations from the active participant from the dialogue context.

Dialogue Control

To start a dialogue call the UDlgManager::StartDialogue static function. You will need to provide a dialogue asset and an array of objects (implementing the participant interface).

It returns with the DialogueContext which can be used to control the ongoing dialogue.

image_7

After the dialogue is started it is already executed to the point where the first player choice is required - selecting the only available option is also considered to be a choice in this case.

You can get the active node data and the currently available options from the context using the following DlgContext functions: GetOptionNum, GetOptionText, GetActiveNodeText, GetActiveParticipant.

If it is possible that the result of the conditions can change during the dialogue after a node became available but before the user picked an option the active options can be refreshed via the ReevaluateChildren function.

Once the player selected an option you can call ChooseChild() with the selected option index to proceed the dialogue. If the function returns with false the dialogue is ended and the context must be dropped.

Dialogue Memory

If you use the long term memory of the dialogue system (for conditions checking if a certain dialogue node was visited or not during the whole game) you will have to serialize the dialogue history.

When saving your game simply call UDlgManager::GetDialogueHistory, and save the returned data structure. On load you can use the loaded value via UDlgManager::SetDialogueHistory.

DlgMemory

When a new game is started (e.g. with a different player profile) you should also clear the dialogue memory via calling the setter function with an empty map, otherwise the system may use the previously used one.

Clearing

To clear the memory you can use the helper method UDlgManager::ClearDialogueHistory in the StartPlay/BeginPlay of your GameMode.

function_clear_dialogue_history

But you don't need to do this by default because the memory is already cleared automatically by the plugin whenever a new world is loaded, change this setting in the dialogue settings under Clear Dialogue History Automatically name.

project_settings_category_runtime

Dialogue Console Commands

To enable commands you have to manually register them using UDlgManager::RegisterDialogueModuleConsoleCommands inside your StartPlay/BeginPlay of your GameMode and unregister them in EndPlay using UDlgManager::UnRegisterDialogueModuleConsoleCommands

console_commands

Example:

gamemode_example

Speaker States

Speaker states can be used to add an extra FName to your nodes and/or edges. The Speaker State of the active node is passed to the GetParticipantIcon() function if it is called via UDlgContext::GetActiveParticipantIcon(). It can be used e.g. to attach emotions to nodes like Happy, Sad, etc. - you can use different images for the different states in your UMG widget. The SpeakerState of an edge can be requested via UDlgContext::GetOptionSpeakerState().

To display SpeakerStates in the dialogue editor you have to change the SpeakerState Visibility property in the dialogue settings.

SpeakerStates also have custom UI picker, but the used values are stored in a global cache.

A Blueprint Select on SpeakerState node is also provided - it lists all used SpeakerState values as wildcard option pins.

SelectOnSpeakerState

Reflection Variables (aka Class Events and Conditions)

dlg_reflection

This feature is useful if you want to directly modify variables inside your Blueprint instead of using your own data storage structures.

Autocompletion

Because the dialogue editor can't know what variables a participant might have you need to set the participant class for it to work. Click on an empty canvas inside the dialogue editor and on the left side (by default) you should the property DlgParticipantClasses.

dlg_participant_classes

4. Helper tools

Blueprint Nodes

image_9

The plugin contains some custom blueprint nodes to help out with the implementation of the condition and event related functions.

They copy the behaviour of the Switch and Select nodes, but they get the participant name of the owner blueprint using the IDlgParticipant interface and gather all the associated values from all dialogues.

image_10

image_11

image_12

Dialogue Browser

dlgbrowser

Click on Window -> Dialogue Browser to open it. The purpose of this window is to gather and visualize dialogue related data.

You can see all your dialogue participants here, check on the dialogues they are referenced in and see the list of associated events and variables.

The events/variables/conditions are also organized by dialogues, and the containing nodes or edges are also listed. Clicking on those will open the dialogue with the associated node/edge being selected.

Search Window

You can use the search window to search in the dialogue texts.

If you want to search inside a single dialogue open the search window via pressing ctrl+f in the dialogue editor.

If you want to search globally use the ones under Window -> Find in dialogues.

search_window

Runtime Display (aka Dialogue Data Display)

You can use the Dialogue Data Display window runtime to list the active participants, their variables/events. It is also possible to modify the values, check conditions or fire events.

To open in editor you can use Window -> Dialogue Data Display

Alternative way to run is the console command Dlg.DlgDataDisplay. (This also works in non-editor builds.)

Before you can use the DlgDataDisplay Window you need to register the console commands of the Plugin. An example is provided in the section Dialogue Console Commands or in the C++ project here.

dialogue_data_display

Dialogue Editor Settings

NOTE: Previous to version 5.0 of the plugin the settings where located here Edit -> Editor Preferences -> Content Editors -> Dialogue Editor.

You can open the Dialogue editor settings via Edit -> Project Settings -> Editor -> Dialogue. Here you can change the layout and the behaviour of the dialogue system.

project_settings

Clone this wiki locally