Making a Dialogue System for Unity

Developing a Dialogue System for Unity

I made a dialogue system that uses Yarn and handled loading those files up and displaying them.

Who wrote this: Kris Gay

Where can I get it: On our Github

This post is about the development of the dialogue system that we have used here at our for our game Gastrobots and our upcoming game Project Giants. It should also serve as a small primer for people using it in their projects.

GastrobotsGastrobots

The targeted platforms for both these titles are mobile devices, iOS/Android and they are both programmed using the Unity Game Engine. I’m going to start with talking about how the need for a custom system came about, then talk about how it was implemented for Gastrobots and then finally I’ll talk about how it was improved for Giants and where it currently stands.

It starts with Giants which is the older game of the two. Giants was designed from the start as a narrative driven game, and we knew early on that we’d need a dialogue system capable of displaying a dialogue tree created by non-programmers, preferably with some visible UI for editing.

—– Early Days —–

In the beginning, I started out looking through the Unity Asset store and quickly eliminating possible options. These fell into two camps, being extreme overkill for what we needed, having systems that include everything and the kitchen sink or not being meeting one of the requirements for the system.

In the course of finding this stuff out and investigating their implementations, we moved over to initial development on Gastrobots and didn’t worry about it for some time.

—– Gastrobots —–

During development of Gastrobots, we decided to given each System (corresponding with the three square meals) a leader.

Breakfast MayorPresident LunchAmbassador Dinner

The idea was that the leader of the system would be an easy subject to hang tutorials on as well as lending the player a bit of context about why they are going around rounding up animals. The basic concept was that they’d just spit some information at you, but we thought it would be funny to have the robot respond in beeps and bloops. Suddenly productive dialogue was an issue again, but I already knew we super didn’t need any of the heavy stuff so making a very simple system should be enough.

Enter Yarn.

The yarn is a fantastic tool. I forget how I found it, most likely a tweet from creator Alec Holowka but finding it laid everything out for how the dialogue system was going to work. Figuring out the data that would be used first, before starting development on the system was an excellent move. If I’d tried to build the visible parts first and fit the data to that, I doubt it would have gone very well.

Yarn Dialogue File

Looking at Yarn, we can see that each “chunk” of dialogue is composed of multiple lines and then connected to other pieces of data by options this lends itself well to an object-oriented representation.

In my dialogue controller, this is modeled by each chunk of data being represented by a ConversationNode. ConversationNodes parse out the Title, Tags (talk about those in a second) and the Lines.

Each Line keeps track of a character name, the actual line and then some optional bits of metadata that I defined and parse out.

A Line

The metadata that is associated with the line was partly self-developed and partly informed by how Yarn works. Options, for instance, are formatted in Yarn like [[Free Text|Destination_Node]] and since I wanted the UI to work as intended, I needed to keep those formatted that way. The solution to that was to split the lines into two segments, the text and the metadata, bearing with the style I used a | to separate them. Keeping the general style that Yarn uses important to me because if you are self-defining something you want to maintain the style as much as possible, this makes it easier to read and simpler to write for your data system, especially important when it isn’t just you writing for it.

Extra Data

In Gastrobots there were only two tags of note, options and emotes. The options tag is universal and just contains a list of Yarn formatting options. This is the driver for what dialogue options show up in the game.

A Line of dialogue

That line being displayed

Emotes were for displaying different pictures or triggering different animations depending on the DialogueContext (in a minute) that the line was shown in, the set of dialogues is controlled by tags which are just added in Yarn and

Emotion change

 

—– DialogueContext —–

The two remaining pieces of the core exchange system are the DialogueContext and the DialogueController. The DialogueController represents the whole exchange file, it controls the transitions between different CoversationNodes and throwing the right actions and change events to the DialogueContext.

The DialogueContext is a pure abstract class with a couple of basic methods for handling data passed to it by the DialogueController. This class is intentionally sparse because it is intended to allow for the greatest possible range of expression.

These are both made using the same backing code, just different DialogueContexts.

Giant Improvements

After Gastrobots had been released, we moved back to developing Giants and spent time using the library tools we’d build doing Gastrobots to improve what we had on Giants. One of the primary tasks for that was replacing the hard coded demo dialogue with our shiny new Dialogue System.

One of the first improvements that needed to be made was to allow the exchange system to inform the program at large of any decisions that were made. The decisions in Gastrobots had no impact on the gameplay; they just selected dialogue trees for the user to read. In Gastrobots the choices you make do change how the game plays, and so we need a way to inform any listeners that a certain choice was made.

Image of Dialogue Actions

The way that I implemented this is what I call Dialogue Actions. Actions are a post-line set of meta-data that encodes a calling key and some string parameters. It is written into the dialogue similarly to how options are except the syntax is action([actionKey|actionParam]). Just as with options, a line can have multiple actions associated with it, and they’ll all be called when the line is sent for display. The DialogueContext can decide what, if any visual indication should happen (for instance passing along an item being acquired to the popup system). The action system is all run through the DialogueController and uses events. You register a dialogue event by calling the RegisterDialogueAction function with the key and a delegate that takes a string parameter and when the line is displayed that delegate will be called with the params as a string for you to read or parse.

Image of replaceable dialogue

The other significant change for Giants was adding replaceable dialogue. This is only written as {KEY} and then when you register KEY, and it’s replacement (say, PRICE and 1) anywhere in the dialogue where {KEY} shows up it’ll just be string replaced by a 1. This happens as close as possible to display time so that we can update values if an update is needed. Like with actions this is all done through the DialogueController.

One thing that hasn’t been done yet is the removal of emotions as a concept on a line. These should be replaced by actions linked to the character portrait through the event system, but that hasn’t been implemented yet.

Open Source

In a first for we’re releasing this code to the Unity developers community. Hopefully, you get some use out of it in your games. The license is Apache License 2.0, and you can get the code on our Github here.

By | 2017-04-05T00:10:36+00:00 April 1st, 2017|Categories: Blogs|0 Comments

Leave A Comment