Core Features
Dialogue Tree
Dialogue Node
Branch Node
Event Node
Conversation Variables Node
Global Variables Node
Node Features
Renaming Nodes
Resizing Nodes
Collapsing Nodes
Deleting Nodes
Dialogue Features
Option Conditions
Dynamic Interpolated Strings
C# Integration
C# Compiling
Integrate with Other C# Components
Compiled Event Scripts
Custom Windows
Node Editor Window / Dialogue Tree Window
Preferences Window
Speech# Localization Window
Variable Window
Audio Assignment Window
Speech# Helper Window
Localization
Localization Databases
Localized Strings
Localized Audio Clips
Shortcut Integration
Audio Clip Interruption
Exporting
Export as a Screenplay
Speech# - Documentation
Speech# - Quick Start Guide
Overview
This asset is for leveraging your experience with programming in Unity to create unique, dynamic experiences.
This system truly lets you tie dialogue events, logic, and branching directly into your existing gameplay systems simply by adding a reference to the scripts of those systems just like with traditional C# scripting in Unity.
General Structure
There are a few key elements to how this dialogue system works:
1. Dialogue Trees / Graph Editor
2. Progressing from one node to the next connected node
3. A “dialogue character” (the character that will be speaking with the player)
The core of this system is built around these key elements.
Dialogue Tree
The dialogue tree is the asset that stores all the nodes you create for a dialogue. All your dialogue and branching logic is written in the node editor then the logic automatically compiled into a C# script. This allows you to take full advantage of the C# language when creating logic and see any errors in the same way you would for other scripts in your game.
Node to Node Progress
Triggering nodes is the basic method of traversing the graph at runtime and each time you want to move from one node to another there is a unified event to call for all nodes. This makes it simple to add new nodes to this system and create your own interface for using your graphs, or you can simply edit the example script provided.
The general flow is to add DialogueCharacter.cs to a character object, write your dialogue in a dialogue tree, generate a script based on that dialogue tree, and then display the dialogue in game by triggering each node to progress.
Dialogue Character
A dialogue character is a GameObject with a specific component/script that can talk in your game. This component, DialogueCharacter.cs, is meant to hold all references to other scripts needed for scripting logic in your dialogue trees.
For example, if you have stats for your character, you could reference that script in the DialogueCharacter.cs script to easily reference those variables when writing dialogue.
The first person example scene included with the asset includes a DialogueCharacterExtension_Example.cs class that inherits from the base DialogueCharacter.cs to collect functions and class references used just for the demo dialogues.
The Nodes
There are 3 main nodes that are used to creating dialogue. The dialogue node, branch node, and the event node that will contain all the data and logic needed to run a dynamic dialogue in game.
There are 2 additional nodes that allow you define local variables accessible in just this dialogue tree or global variables that can are accessible to all dialogue trees and other systems in your game.
Dialogue Nodes
Dialogue nodes contain the speech that the character will say to the player and then any options the player has available to respond to the character.
Each option for the player also has a red text field under it that can contain logic required for the option to be seen by the player. These should be written as you would for the contents of an “if statement”.
Think of any logic placed in that field as being the contents of an if statement. The plus and minus buttons will add or remove dialogue options to the node, always adding and removing from the bottom.
Branch Nodes
Branch nodes are how you check a simple condition to go to one of two different directions in a conversation.
This could something simple like checking if the player has spoken to the character already to have a different response or chaining multiple branches together to create a precise response to the current player’s world state.
The text you write in this field is much the same as the conditions for a dialogue option and should be written as you would for an “if statement”.
Event Nodes
Event nodes are a block of code that will run just like any normal C# function.
Anything that you can write in C# can be added to an Event node whether that be sending a notification of to the player, changing how a character thinks about the player, or activating an entire system unique to your game.
The one thing to keep in mind is that anything you want access to when scripting in the dialogue tree should be added to the DialogueCharacter.cs script (or an inheriting script) for ease of use.
Conversation and Global Variables Nodes
The final two nodes are the Global Variables and the Conversation Variables nodes.
The Global Variables nodes from all dialogue trees will be added to one script called Globals.cs and any variables you define in this node will be easily accessible from all dialogue trees.
The Conversation Variables node is where you define any variables you only need to be accessible within the current dialogue tree you are working on.
Creating a Dialogue Tree
As mentioned, the dialogue tree is just an asset that you can create like any other asset, but there is also an easy way to add a new tree from the DialogueCharacter.cs script on a GameObject.
This asset will have a default location to be created that can be changed in Speech#’s Preferences menu.
There are several other generated assets that also have default locations you can change to help streamline the workflow of writing dialogue for multiple characters, but there is also an option to choose where you want to place an asset each time you create one.
Using the Dialogue Tree
Whenever you make a new dialogue tree there will be a starting Dialogue, Global Variables, and Conversation Variables node already created.
The starting node for any graph is the node that does not have any inputs to it and so it is likely best to build out from the default dialogue node.
Adding Nodes
To add more nodes simply right click in the graph view and select the node type you want to add.
Right clicking on the graph and moving your mouse will allow you to move your view of you dialogue and the mouse wheel will let you zoom in and out.
There are also several settings in the Preferences menu to adjust how the graph works and appears.
Connecting Nodes
Once you have multiple nodes you can connect them by simply left clicking on an output and dragging to the input of another node.
If you need to create a specific path for a node tether, press right mouse button while dragging the tether to pin the that part of the tether to the graph view.
Common Mistakes
When creating a dialogue tree make sure that there is not an output leading to two branch or dialogue nodes directly. Make sure that it is always clear what node should be next or create a branch node to have logic for choosing between two progression paths.
Minimizing/Maximizing Nodes
To help keep things clean to look at or reach through there is a minimize and maximize button in the bottom left of each node. This will only show the necessary information for reading the dialogue and options while hiding the logic used to traverse the tree.
To maximize or minimize all nodes there is a helper function that can be seen when right clicking on a blank part of the graph. There are a few other helper functions available in this menu that may help when creating trees.
Recording Dialogue Audio Clips
There is a field to record dialogue for the character speaking or you can drag an existing file into the node once you have a completed recording.
If you plan to have voiced dialogue, I suggest recording yourself saying each line in the dialogue graph to help with testing, editing dialogue, and to help predict the time needed for recording with an actor.
Assigning Final Dialogue Audio Clips
For assigning final audio clips more easily there is a “Audio Assignment Window” that can make it much easier to assign to the intended dialogue tree.
Ending Dialogue Tree Conversations
Whenever a dialogue is complete, I suggest having an event node that calls whatever logic you want to use to end the dialogue.
There is a default function that can be referenced from any dialogue character simply called “EndDialogue()”, which is set up to work with the example conversation UI.
I think it is best to do that is an event node each time because it allows you to have an easy place to add any other logic you want when ending the conversation.
Dynamic Text
To compliment the dynamic nature of your dialogue you may need to display variables in your text. This is achieved by creating each line of dialogue as an interpolated string.
Basically, what this means is that if you type a variable name between a “{” and a “}” then the value of the variable will display in the dialogue.
For example, if you have a string variable “playerName” with the value “Joe” then the dialogue “Hello, {playerName}, how are you?” would display as “Hello, Joe, how are you?” You can also use expressions and any other features of interpolated strings in C# to make your dialogue more dynamic.
Creating and Using Variables
As mentioned, there are two different nodes that allow you to make new variables.
These can be useful for tracking information about the player’s choices or when you need a state that multiple dialogue trees need to reference. Any time you are working with data or variable names in a dialogue tree, I would suggest defining it as a variable.
This can make the logic read more clearly, but also allows you to easily test multiple dialogue states by simply changing these variables in the editor. To references a global variable when writing in the dialogue graph you must write “g.” followed by the variable name you want to reference.
Variables Window
There is a variables window available for viewing the global variables and the local variables of each character that are defaulted to being read only.
This is helpful to ensure that the starting state of dialogue is always as you intended but for testing it can be useful to have them be changed in the editor.
To make all variables editable you need only change the setting in the Preferences menu and recompile all scripts from this window. Then you can edit variable values as much as you want.
The Event Generator
The DialogueEventTrigger.cs script included with this asset is an easy way to author content that interacts with the global dialogue variables you defined. It is set up to reference global variables the same as the dialogue trees by typing “g.” followed by the variable name you want to reference.
DialogueEventTrigger.cs also has a C# event that will be automatically assigned to run your custom code so to trigger this code you need only trigger the even from DialogueEventTrigger.cs
This system is included just for the convenience of creating dynamic content, but all variables can also be referenced the same way as any other C# script in Unity.
Setting Up a Scene
For a scene to work you only need a few key things: a player with a DialogueCharacter.cs component, a GameObject with the Globals.cs component, a UI manager for displaying dialogue, a character with a dialogue tree and a generated script, and your preferred system for displaying and progressing through the dialogue.
I have included examples to how these scripts could be set up and a prefab GameObject called “DialogueManager” that provides my versions of the needed scripts.
Recommendations for Customizing
Most of what I have made is based on the dynamic laid out in “General Structure” section of this document. Because of this, most of the scripts I’ve written have some dependencies on this structure.
It’s certainly possible to rewrite your own versions of all of this with your own assumptions and that may be necessary if you have a particularly unique dialogue mechanics planned for your game, but to keep adoption simple I would recommend adding additional needed logic or references to an inherited class of the DialogueCharacter.cs component.
The DialogueCharacter.cs component and inherited classes are the core script that a “character” in this system is built around. It is what provides all references for the dialogue trees to make writing logic and connecting to other core systems as easy as possible.
If you want to add other systems that should be easily referenced in the dialogue trees then you can look at how the Globals.cs is referenced in generated dialogue C# files and change the template that these scripts are generated from.
Through editing DialogueCharacter.cs and the templates of generated scripts, it should be easy to accommodate any system and will make it easier to build onto this system, rather than remaking it from scratch with a slightly different set of assumptions.
Exporting
To make easy for actors to record your dialogue, you can export a text file in the screenplay format. There is a guide to using the exported text file in the “Dialogue Screenplays” folder.
And there is additional information on the documentation section of the website.
Core Features
Dialogue Tree / Node Graph
The dialogue tree is an asset that displays as a node graph.
Double click on a dialogue tree asset to open the node graph editor for a dialogue tree.
These dialogue trees contain all the dialogue and logic for your in-game conversations.
The dialogue tree’s node graph editor has several features to help with organizing your dialogue trees. Right click on the background of the dialogue tree editor to bring up a menu that lets you create nodes and manage the tree with generalized functions.
Dialogue Node
Dialogue nodes contain the speech from the characters in game and the player response options.
There is also a display of the audio file that is assigned to the character’s speech as well as a button to record placeholder or test dialogue for a character’s speech.
Each of the player response options include a section to input C# logic that determines if the option is possible to be selected or not. Think of this as being the contents of an if statement conditional.
Branch Node
Branch nodes contain logic that with decide which node follows the node that inputs to the branch node. Think of this as being the contents of an if statement conditional.
Event Node
Event nodes contain C# code that will compiled into a function that is called whenever this event node is triggered. Think of this as being the contents of a C# function that will be automatically generated.
Conversation Variables Node
Conversation variables are C# variable definitions only accessible to the dialogue tree they are defined for.
Global Variables Node
Global variables are C# variable definitions accessible to any dialogue tree in the project. To reference these variables, type a “g.” before the variable name in the node.
Node Features
Renaming Nodes
All nodes have the option to rename the nodes.
Rename a node by right clicking on the name at the top of the node and selecting “Rename”, then simply type the new name for the node and click the “Apply” button.
There are several other options for nodes that become available in this menu.
Resizing Nodes
Each node can be made wider or slimmer by clicking the 3 diagonal lines in the bottom right of a node and dragging the mouse the direction you want to expand or contract the node.
Each node type has a limit to how much it can be shrunk to ensure the nodes always have good readability.
Collapsing Nodes
All nodes have the option to collapse the nodes.
The button at the bottom left of the node will collapse the node to a more compact streamlined version great just for reading through dialogues.
Collapsed nodes can be resized to be smaller than non-collapsed nodes.
Right clicking on the node graph background and select “Minimize All Nodes” or “Maximize All Nodes” to collapse or un-collapse all nodes in a dialogue tree.
Deleting Nodes
All nodes can be deleted.
It is best to make sure each dialogue tree has only one conversation variable node, only one global variable node, and at least one dialogue node.
When a node is selected (indicated by the highlighting around the edge of a node) the “delete” key will delete the node.
Additionally, you can right click on the header at the top of the node and “remove” in that dropdown menu.
Finally, if you have several nodes created in a dialogue tree that aren’t being used for anything and aren’t attached to other nodes you can right click on the node graph background and select the “Clear Unused Nodes” option from that drop-down menu to remove all these unused nodes.
Dialogue Features
Option Conditions
Each of the player response options include a section to input C# logic that determines if the option is possible to be selected or not. Think of this as being the contents of an if statement conditional.
Dynamic Interpolated Strings
Interpolated strings are a way to insert variable data or logic into the construction of a string. This is a feature of C# for constructing dynamic strings more easily denoted by a ‘$’ in front of a string definition ex. $”Hello” and variables and logic are inserted using ‘{’ and ‘}’ around it within that string.
Inserting logic in this way would look like: var nameVar = “Joe”; string finalString = $”Hello, {nameVar}!” which would display as “Hello, Joe!”
As mentioned, this is meant for the dynamic construction of a string, it is not meant to be a string that dynamically changes. However, for games these values may change a lot, stats go up and down, events get completed, and names can change. To incorporate all the amazing functionality of interpolated strings and have them be dynamically changed with runtime variable changes each dialogue string has a generated function for constructing the string when the dialogue starts.
C# Integration
C# Compiling
Each dialogue tree on a character has an associated C# script that is generated based on the content of the nodes within the tree.
This is useful for features like the dynamic interpolated strings you can read about in the documentation, getting different strings based on the current language setting, and it enables all of the C# logic used to branch dialogue, have conditional options, and to call C# code directly from event nodes.
This generation of a script is done using a template for the inherited class that all of this logic goes in and the inputs from the nodes are organized into specific functions for each element of a dialogue tree. Then each of the nodes in the dialogue tree have those functions assigned to events within the node which get triggered when the node is traversed to in game.
This also means that if you make any logic errors in your nodes, misname variables, or forget certain syntax all of these issues will surface as errors in the console just like any other C# error you get with other scripts in your project.
Integrate with Other C# Components
Each tree getting their own generated C# script is useful for easily integrating your characters and dialogue with the rest of the C# from your project. See the C# Compiling documentation to learn how this works with the system.
Because each character gets a C# compiled script and have a DialogueCharacter component to facilitate dialogue you can easily set up an inherited class that takes all of that based functionality and adds the functionality that’s specific to your characters in your games. Additionally, you can easily create references to other components your characters have and easily reference them within your dialogue trees for logic or for populating data into your dialogues.
Compiled Event Scripts
As an easy way to integrate custom written C# code that can interact with dialogue system global variables or general write bespoke functionality for in game content a way to compile C# formatted strings into a generated event script is provided.
Custom Windows
Node Editor Window / Dialogue Tree Window
The node editor window is opened when you double click on a dialogue tree asset to edit the dialogue tree.
Preferences Window
The preferences window in the Unity editor has an additional section added for Speech#. The options here allow you enable and disable several automatic elements of the system included several options for helping to debug your dialogue trees in game.
Speech# Localization Window
The Speech# Localization Window lets you inspect the localization database of characters, dialogue tree assets, and localization database files. Either select a Dialogue Tree Asset, a character in the scene with an assigned Dialogue Tree Asset, or select a Localization Database Asset.
The window will display all of the localized strings and allow you add text or files to the database.
Note that the dialogue trees manage their own database directly so it isn't recommend to store generic strings within a dialogue tree. Instead create a separate Localization Database Asset and then reference it's strings where needed.
Variable Window
The variable window is a Speech# specific tool for debugging your character conversations at runtime. It collects all of the global variables from character and shows the character specific dialogue variables organized by the name of each of the currently loaded characters.
Whenever there is any functionality that doesn’t seem to be working as intended you can check the current state of any variables in this window and figure out if it is a logic issue or if variables are not being set as you’d expect.
Audio Assignment Window
The audio assignment window is an easy way to assign audio clips for each character in your scene. While the option to assign the audio clip is still an option in the dialogue tree itself this window is there as a conveniently organized way to assign more finalized clips all at once rather than needing to open each dialogue tree editor individually.
Speech# Helper Window
This window is just to give you quick functions to manage all the scripts for this asset.
Localization
Localization Databases
Localization databases are a collection of strings, audio clips, and their respective hex ID for referencing them.
The LocalizedDataManager script included with this asset is an example of how you can reference strings and clips from localization databases.
The Speech# Localization window will allow you to view and edit localization databases by selecting the characters in the scene, or you can select the localization database files directly in the assets folder to edit them in the inspector.
Localized Strings
Localized strings are text that can be accessed per the reference hex ID. Read the Dynamic Interpolated Strings and the Shortcut Localization documentation to see more features available for localized strings and how they work.
Localized Audio Clips
Localized audio clips that related to the localized strings. Read the Shortcut Localization and Localized Audio Clip Interruption documentation to see more features available for localized audio clips and how they work.
Shortcut Integration
To make using localized strings easier there is a shortcut feature for adding localized strings into dialogue text.
When your strings get compiled into C# functions the system looks for the needed data within the ‘<’ and ‘>’ angle brackets to replace with functions that pull in localized strings. For strings you just need to have the index of the localization database from the LocalizedDataManager list and the ID of the string in the database. If you are referencing a string in the default global localization database (called “Default Localization Database”) then you need only paste the ID.
To reference a string from the “Default Localization Database”:
<000F23> will be turned into: {loc.Str("000F23")}
To reference a string from a LocalizedDataManager list:
<14:000F23> will be turned into: {loc.Str("000F23”, 14)}
Audio Clip Interruption
To make using localized audio clips easier there is a shortcut feature for interjecting audio clips partway through the main dialogue clip assigned to a character’s speech. This means your main dialogue clip will just have a blank spot in the dialogue for you to insert the dynamic localized clip.
When your strings get compiled into C# functions the system looks for the needed data within the ‘<’ and ‘>’ angle brackets to replace with functions that insert a localized audio clip.
For audio clips you need to have the index of the localization database from the LocalizedDataManager list, the ID of the string in the database, and then the time in seconds where the clip should be interjected. If you are referencing an audio clip in the default global localization database (called “Default Localization Database”) then you need only paste the ID and then the time in seconds where the clip should be interjected.
This interjection function also automatically returns the localized string as well as initiating the clip interjection to happen at the defined time.
To reference a string from the “Default Localization Database”:
<000F23,9.78> will be turned into: {speaker.InterjectClip(9.78f, "000F23")}
To reference a string from a LocalizedDataManager list:
<14:000F23,9.78> will be turned into: {speaker.InterjectClip(9.78f, "000F23", 14)}
Exporting
Exporting as a Screenplay
When you chose to export your dialogue as a screenplay it exports both a .txt file and a .rtf file to Assets>Speech#>Dialogue Data>Dialogue Screenplays.
The .rtf file format is no longer supported but exports with most of the usual screenplay formatting included.
To ensure future options the .txt is included with no formatting, but there is a guide below to set it to standard screenplay formatting.
Disclaimer: This is my attempted solution to formatting non-linear screenplays. If you find something else works for you use that and also, let me know about it and I will include it in the Speech# asset for other users to benefit from.
How To Format The .rtf File Like A Screenplay
To set the exported .rtf file to match typical screenplay format all you need to do is set the left margin to 1.5 inches. All other margins should be set to 1 inch. The rest of the formatting for .rtf is done on export.
How To Format The .txt File Like A Screenplay
The exported .txt file contains all the spacing and text expected of a traditional screenplay.
Some new elements are added too such as the addition of dialogue options, the numbering of these options, and indicate what options lead to each line of dialogue.
For these reasons, the already dense screenplay format is made even more dense with information, but the hope is that this way of presenting non-linear dialogue is helpful to the actors that read them.
General Formatting
- The font should be set to “Courier” or “Courier New”.
- The font size should be set to 12 pt.
- If the script is to be printed, set the left margin to 1.5 inches.
- Set all other margins to 1 inch.
- Bold all instances of “START” and “FROM”.
- “Line Spacing” should be set to 1.
- The “Spacing” “After” each line spacing should be set to 0.
- Optionally, bold all numbers for dialogue options.