How I Created a Dialog System For Unity

How I Created a Dialog System For Unity 

Art by Amberdragon6666 on itch.io

For the past while, I've been working on a team of two on an escape room visual novel puzzle game called A Box of Stories. For the game, we needed a dialog system, and in this blog post, I will talk about how I went about making this system.

For context, I had made very basic dialogue systems before. These worked by calling a push method to push dialogue to a dialogue queue. Then, when dialogue was being read, the front of the queue would be dequeued and the characters printed one by one to a dialogue box. This sort of system is great for games that don't have a heavy focus on dialogue systems, but for story driven, visual novel style games, something better is needed. There's also the issue of hardcoding dialogue sequences. That's bad. We don't want to do that, so with this new project, I wanted to use separate dialogue files that would be loaded and parsed by a dialogue parser and printed into a dialogue box by a dialogue handler. Side note: It's very hard to remember to spell dialogue with the British English spelling after all the time I've spent programming this, since convention is to use the American English spelling.


The dialogue parser's job is to load and read a dialogue file and turn it into data that is understandable by the dialogue handler. I decided to use a command pattern approach. Dialog files would contain commands, and these commands would each be used to instantiate a dialogue command object which would be added to a dialogue command queue. A dialogue command object can be executed with the Execute method. I used a coroutine to sequentially execute command objects in the queue.
I also used a coroutine to handle the character-by-character printing of dialogue into the dialogue box.
I won't go to into detail with code, but I plan to clean the code up and release the system as a Unity package called Diadem.

Here are all the features I implemented into the dialogue system during the development of the game:
  • Playing looping music and ambience to their respected mixer groups and being able to fade in and out.
  • Playing one shot sound effects.
  • A command to await player input before executing the next command in the queue.
  • Commands to set backgrounds or animated backgrounds with the ability to crossfade between them.
  • A command to set the character name.
  • Commands to handle printing, clearing and continuing of dialogue.
  • Commands to define sequences.
  • A branch command which can branch to sequences in the same file or in another file.
  • Flags which can be added, removed and are automatically saved between sessions.
  • Conditional commands to check whether or not a flag has been raised.
  • Font commands for controlling the look of text.
  • A choice command which creates a choice button with text and runs the specified command when pressed.
  • Hiding and showing the dialogue box with or without a crossfade.
  • A command to load a unity scene.
  • A wait command.
Roadmap:
  • A sprite command to add, remove and control foreground sprites. For example, character sprites.
  • Command aliases such as "say" instead of "dialog" and "name" instead of "character_name".
  • Improved audio commands. I think there should be one audio command. A mixer group, whether the audio should be looped or not, starting volume and whether to fade in or out should be specified. I may also use an ID system where a sound is given an ID within the command so it can be referenced later.
  • More background transition effects. I will also apply these transition effects to sprites.
  • A more robust parser. One current issue is that semicolons, that break commands up, are still counted if they are wrapped in double quotes. I'll need to make better use of regex expressions to handle cases like this.
  • A graphical dialogue tree designer similar to Unreal blueprints or Unity's animation system. The underlying systems would be the same. The graphical designer would create a dialogue file.
So how do the dialogue files look? I wanted to make the commands simple and understandable, so that anybody could read it and get an idea of what was going on. You can define as many different sequences as you like in a dialogue file, and switch between different sequences in the same or different files using the branch command.


There are certainly some things I will change. Some commands would be renamed, and I think I'd create command aliases for frequently used commands. For example, the dialog command could have the alias ‘say’ or maybe ‘d’. Less common commands such as ‘choice’ would not be given aliases, as to maintain readability. I think I'd also change some command names such as character_name to name. Furthermore, I'd combine some commands. I'd like to combine the fade_music and music commands and the fade_ambience and ambience commands. I'd also like to add commands handling foreground sprites. If I were to release this publicly, I may add a GUI for constructing dialogue files. I think the best idea for this would be to make a flowchart like GUI, like UE5’s blueprints or Unity’s animation system.
Of course, it is not yet in a perfect state, but the system I programmed has worked perfectly for the project and its scope, allowing me to easily implement our stories into the game. 

In total, the system is made up of 1300 lines of code! It was a super fun project to work on, and I look forward to improving it. I've released some docs which I will update as I develop Diadem. You can have a look here!



Comments

Popular Posts