[WIP] Dialogue System Example Blueprint Implementation [Deprecated]¶
Implementation Overview¶
- This is somewhat outdated now, the project this guide was based off of has been updated to be more modular using components and also handles player choices. This guide is being left as a reference and may be updated in the future.
The goal is to create a functional dialogue system using the ThirdPerson template where each individual character contains their own dialogue state machine.
The player should be able to interact with NPCs to start a dialogue.
Once implementation is complete only state machines will need to be used to design conversations just by editing text directly on nodes.
You can download the project used for this guide from GitHub. Project is newer than this guide!
Blueprint Prerequisite¶
We will need to setup normal blueprints before creating our state machine implementation.
- UMG Widgets
- For displaying the dialogue
- Dialogue Manager
- For storing and retrieving the dialogue UMG widget
- Should be global, the Game Mode will be used for this implementation
- Base Character Blueprint
- Needs to be modified to start conversations, store the dialogue state machine
- Input Handling and Third Person Character
- ThirdPersonCharacter needs to listen for input and find NPCs to talk to
UMG Widget¶
The UMG widget is responsible for rendering the text to the user
- Create a new UMG widget called
DialogueUI
for displaying the speaker name and the dialogue text body. - The textblocks should be variables.
- Create a function
DisplayText
that sets the dialogue text and speaker text.- We use a function rather than binding because binding is less efficient.
- In this example there is a vertical box which sets the maximum size for the dialogue text.
- For assistance creating UMG UI please see the official UE documentation.
Dialogue Manager¶
A global manager for accessing the dialogue UI. This is in the game mode for this implementation.
- Open the ThirdPersonGameMode blueprint.
- Add a new variable of type
DialogueUI
. - Create two functions,
DisplayDialogueUI
andCloseDialogueUI
. DisplayDialogueUI
is responsible for creating the widget if it doesn't exist, adding it to the viewport if it isn't already there, and then returning the dialogue widget.
CloseDialogueUI
removes the widget from the viewport and clears the variable.
Base Character Blueprint¶
We're going to use a new base character blueprint as a parent between our NPCs and player characters to share common functions. You could use an interface for this as well, but most of this functionality just needs to be defined once on a base class.
- Create a new blueprint extending the
Character
class and call itBaseCharacter
. - Add a State Machine Component called
SMDialogue
. Leave the component settings default. - Create a member variable of type text
CharacterName
. You can default the value toNPC
.- Create a pure function
GetCharacterName
with a return type of text which returns theCharacterName
.
- Create a pure function
- Create a member variable of type BaseCharacter with name
CharacterInConversationWith
. - Create an event dispatcher called
ContinueDialogue
. - Create a function
NotifyCharacterInConversation
that accepts a BaseCharacter argument and sets the CharacterInConversationWith
- Create a pure function
IsInConversation
that checks that theCharacterInConversationWith
is valid and returns a bool.
- Create a function
StartDialogue
with a parameter of BaseCharacter.- This will call
NotifyCharacterInConversation
both for this character and the Other Character.
- This will call
- Create a function
StopDialogue
which will notify both characters they are no longer in a conversation.
Input Handling and Third Person Character¶
-
Add an input action to your project called Talk and assign it a key.
-
Reparent the
ThirdPersonCharacter
blueprint to useBaseCharacter
. - Overload
NotifyCharacterInConversation
, call its parent, and stop movement if the other character is valid.
- Add a float variable
TalkDistance
and set the default to150.0
- Create a new macro
FindCharacterToTalkTo
.- This will trace for characters in the direction you are facing within the
TalkDistance
range and return a BaseCharacter on success.
- This will trace for characters in the direction you are facing within the
- Finally, in the event graph listen for the input action
Talk
. Here we want to either start the dialogue or call theContinue Dialogue
event dispatcher of the other participant.
State Machine Nodes¶
We need to create several node classes that will be reused in our dialogue state machine graphs. See the Pro Quickstart Guide for creating node classes in Logic Driver.
Base Dialogue Node (State Class)¶
It's worth creating an abstract base class for dialogue nodes so we can extend it for normal text nodes and eventually choice nodes. Our goal is to make this class effictively own the current dialogue segment, be reponsible for displaying the text, and determine when the state should end.
- Create a state class called
FSMNode_DialogueNodeBase
. - Uncheck
Register with Context Menu
in class defaults so this node won't show up as placeable in the state machine graph. - Add a variable of
BaseCharacter
calledSpeaker
type and make it public. - Add a variable of type
SM Text Graph Property
calledDialogueText
.- This is a special Logic Driver variable which creates formatted a text graph on the node.
- It doesn't need to be made public, TextGraphProperties always display on the node.
- Add an event dispatcher:
GoToNextDialogue
- We will use this to switch dialogue nodes.
Functions¶
Should Dialogue End¶
- Create a Pure function with a bool return type called
ShouldDialogueEnd
. - For now just check if the state is an end state.
Handle Dialogue Continue¶
- Create a normal function called
HandleDialogueContinue
- This is the normal operation to determine if we should go to the next dialogue or end.
Event Graph¶
- The base graph will bind to the character's
Continue Dialogue
event dispatcher. When this event fires we will callHandle Dialogue Continue
. - On State Start will display the dialogue UI and send it our speaker name. We also break the Dialogue Text to get the result.
- On State End we check if the dialogue is over and close the UI if necessary.
Dialogue Node (State Class)¶
General dialogue nodes that display text. These will be what we place in the graph.
- Create a state class that inherits from
FSMNode_DialogueNodeBase
calledFSMNode_DialogueNode
. - Check
Register with Context Menu
in class defaults.
Dialogue Transition (Transition Class)¶
Transitions will check if the previous dialogue node should exit.
- Create a transition class named
FSMNode_DialogueTransition
. - Set
CanEnterTransition
to always returntrue
. - In the event graph override events
Event On Transition Initialized
andEvent On Transition Shutdown
- Get the previous state, cast to
FSMNode_DialogueNodeBase
and bind to the event dispatcher we created earlierGoToNextDialogue
. Make sureSetCanEvaluate
is set to false on Initialize, and set to true when the event is called. - In the class defaults, add a behavior rule under
Allowed Connections
. Set theFrom State
to use the state class ofFSMNode_DialogueNodeBase
. This will automatically place this transition when dragging from any type of dialogue node.