Open source feature-rich dialogue system in Godot, with an in game example.
- Branching dialog
- Show dialog depending on previous choices
- Looping dialog: it is possible to repeat dialog by setting
next
dialog text to be itself
- Conditional dialog
- Show dialog and choices depending on in-game variables
- Display custom variables in dialog text using special characters
- Execute actions with dialog
- Easily shake screen, add and remove items from player inventory, and so on, all from the comfort of a single .json file
- Emit signals as needed to play animations, sounds, and anything else you think would be necessary during dialog
- Easily customizable
- Use of control nodes makes it easy to re-size, and use themes or textures of your choice to change the style of dialog
- Possible to use different styles of dialog depending on the speaker
- Beautiful sound and voice 🔈
- Separate voices database allows you to easily change voice per dialog
- Typewriter style sound with simple modifications allows for a wide variety of sound with little effort
- Button sounds are satisfying and responsive
- Separate voices database allows you to easily change voice per dialog
- Animated character icons
- Uses RichText - compatable with BBCode for fun text styles
- Keyboard accessible
- All dialog actions are navigatable by keyboard - no mouse needed!
- Scalable
- Modifying dialog from a single .json file allows for dialog to be scalable to large sized games -- adding dialog takes no more effort than typing the dialog up (no game engine shenanigans needed!)
- Optional parameters makes it simple to use for small games too
Includes an example of how the dialog system might work with a top-down RPG. However, it is easily used for other styles of games as well with minor to no modification, eg. visual novels, etc.
Refer to and download the copy_this
folder on how to setup the dialogue system for a new project.
Navigate to UI\dialog\dialog.tscn
to see how the dialog system works.
You add dialog to your game via .json file, currently stored in Data\Dialogue.json
.
Three examples of adding dialog to your game:
"robust_text_id" : {
"name": "Qin Tina",
"icon": "most_beautiful_being",
"voice": "sparkly",
"text": ["This is the most feature-rich dialog with choices you can make.",
"Don't you think this is so cool?!?"],
"choices": [
{"text" : "Agreed.", "next" : "text_id_if_agree", "action": ["show confetti"]},
{"text" : "Disagreed.", "next" : "text_id_if_disagree", "action": ["go to jail"],
"show_only_if": "player status insane"}
],
"action" : ["screen shake", "play_sound cheering"]
},
"conditional_text_id" : {
"text": ["You can move to the next dialog text depending on in-game variables."],
"next": [{"id": "text_id", "if": "already talked"},
{"id": "other_text_id", "if": "has 5 specific_items"},
"fallthrough_text_id"],
},
"simple_text_id": {
"text": ["This is the simplest dialog you can make."]
},
You can also create custom dialog in-game by creating dialog text in the format specified above and adding it to db_dialog
, a database of all dialogs. This will allow for easier creation of dynamic text that might display in-game variables, but will need some set-up to generate the entry.
Use "actions"
to execute external events, which currently occur at the beginning of the dialog.
“choices”
sets buttons that players can select, and their selection may lead them to different dialogue by setting “next”
text_id. (This is branching dialogue.) You can nest actions in this to execute so that it executes only if the player selects this choice.
You can add in commonly used variables in dialog using reserved special characters. For instance, if the player name is John Smith:
"text_id": {
"text": ["Hello, &."]
},
will display in game as
Hello, John Smith.
You can also dynamically control text speed in a single dialog:
"text_id": {
"text": ["I'm s|t|u|t|t|e|r|i|n|g. This ||| is a longer pause."]
},
will add pauses where the reserved special character |
.
Code is easily modifiable to change reserved character, and to add more special characters with custom behaviors.
It is easy to create new typewriter-style voices yet there is a lot of nice variability in sound possible. You can make new voices using .json file:
"narrator" : {"rate" : 4, "pitch": 1.5, "pitch_range" : 0.2 },
"bird" : {"rate" : 4, "sound" : "chirp", "pitch": 1, "pitch_range" : 0.2 },
rate
: The rate at which a sound is played counted in sound per letters + 1, such as every letter, or every 5th letter. Bigger rates lead to less frequently played typewriter sound.
pitch
: The pitch at which to play the sound.
pitch_range
: A random ± amount in which the pitch can fluctuate. Bigger pitch range leads to more natural song-like voices while lower pitch range sound more monotonous.
sound
(optional): The sound to play in the typewriter effect, matching the name of the respective preloaded sound in the dialogue_voice.gd
in Dialog.tscn
. If no sound is specified, it uses a default sound.
Navigate to the Icon
node at TextBox/Margin/HBox/PanelContainer/Icon
under the dialog.tscn
. Simple add your animations there. For simplicity, it is currently an AnimatedSprite, so please use frame-by-frame animation such as with a spritesheet. Make sure the name of the animation is the same as the name you use as value under the "icon"
key in your dialogue .json file.
Inevitably, you may want to change the style of the dialog system to fit your game. I'll list a few tips as to how you might change the code best:
Navigate to the dialog.tscn
. Under current PanelContainers, change the panel style used under custom_styles/panel
. Change the theme of the root Dialog node. You can also add a NinePatchRect as children of the PanelContainers to change dialog panel texture if you prefer.
⦿ I'm making a visual novel style dialog and want character portraits to have transition animatons (or some other fancy animation)
Currently, I use an AnimatedSprite as the character icon for simplicity. If you'd like to add transition animations (fade in/out, slide in/out, etc.) simply attach an AnimationPlayer to the icon. Feel free to define an extra "animation" key in the dialogue database and add code to start an animation accordingly.
Luckily, this is an easy change, especially with Godot's control nodes. If you change the position of the character icon, simply move the icon outside of the current container to your preferred location and update the node path in dialog.gd
to point to the right node. Similarly, move buttons by changing containers.
You can also change the type of containers! For instance, you can use a GridContainer instead of the current VBox if you wanted each choice button to be formatted in a grid instead of a column.
Navigate to Gamesrc/Globals.gd
and look at the execute
function. At the beginning of dialog, it will call this function with each act in actions to execute.
For actions like “shake screen”, “play_anim animation”, and “play_sound sound”, it will emit a signal to make cinematic stuff happen. With some other functions like “player inventory add 1 mochi” or “data set talked_to_NPC true” it will directly modify in game variables. Feel free to edit this code to add any actions you think your game will commonly use during dialogue.
Use an AnimatedSprite and/or AnimationPlayer to change the animation/sprite depending on where you are in the dialog. Navigate to continue_dialog()
in dialog.gd
and play animation accordingly. I have commented the code well so you should know which block to put it in.
Take advantage of the conditional text functionality! Navigate to Gamesrc/Globals.gd
and look at the is_condition_met
function. You can define new conditions here. Now, imagine if you combine this with a random number generator, and pass in the probability of getting to a certain next
id in the parameter... :)
You can loop dialog by setting next
text id to be its own text id.
To loop a certain number of times, you can take advantage of conditional text (ie. loop only while repeated less than a certain number of times), and setting a data
variable holding the number of times repeated to increment. Navigate to Gamesrc/Globals.gd
and modify the execute
and is_condition_met
function to make this work.
⦿ I have something else I want to do, but I'm not sure how to do it. Is this possible with your dialog system?
Anything is possible with a bit of work! :) If you're stuck, though, I'd love to help you learn. Feel free to message me and I'd be happy to take a look when I have time.
I find .json the fastest to edit and manipulate, since it's basically a text file. No need for graph nodes or other visual UI that gets cluttered when the game grows large.
However, it is admittedly error-prone if you mistype something. Adding error-checking is something I plan on doing in the future.
I do understand editing dialogue via something more visual would be a nice feature though. There are many great visual dialogue editors available that output .json files:
Remember that all you really need is a .json file in the right format, so a dialogue designer for any game engine or story format that outputs to the correct format will work -- do not limit yourself to Godot. In fact, I chose to use a .json file instead of in-game engine specific files as the dialogue data to be compatible with most editors, game engines, and other tools -- if you ever chose to move your game from Godot to another engine, using a Godot-specific dialogue database would've proved to be a massive waste of time and resource.
While it may need some editing to work with my particular dialogue file, it is a good starting point. Please let me know if you would be interested in a visual editor for my dialogue system and I would be happy to look further into developing one suitable to use with this.
I wanted to show an example of how the dialog system may be used as part of a game, and how well it can integrate into game mechanics. It's easy to find open source dialog systems for Godot that shows you how to display text. The hard part is how you can make the dialog integrate well into your game, and respond to in-game conditions, without requiring a whole bunch of repetitive and extra code.
The code and files are also well separated and organized -- dialogue-system specific files are under UI\dialog
. You are free to ignore the other code and peer into that only if you'd like.
Personally, I found project source files rather than plugins easier to understand and emulate when I just got started learning Godot. Plugins are also harder to fully customize/edit to your game style, as the code is often hidden and certain options will not be customizable unless the plugin explicitly allows for it.
If you feel a plugin would be more useful, though, please message me and I will consider making one in the future if enough people are interested.
The project is licensed under MIT license. Please feel free to use for your games, whether commercial or non-commercial! Just be sure to credit me!
Dialog system by Qin Tina
> linktr.ee (https://linktr.ee/qintina)
> RedBubble (https://www.redbubble.com/people/EggcatAndBird/shop?asc=u)
> Github (https://github.com/QueenChristina)
> Twitter @QuailTina (https://twitter.com/QuailTina)
> Youtube @Bok Bok Chicken (https://www.youtube.com/channel/UCojtnxNTvUINEd7-zDUWDfg)
Exceptions:
- Music
- The music is made by Joshua McLean, licensed under Creative Commons Attribution 4.0 International
- Dialogic
- My personal favorite, the most complete open source Godot dialog-system plugin out there. You can create and edit dialog from within the engine itself.
- Game Endeavor
- Insight into how Game Endeaver implemented their dialog system gave me insight into how I might execute actions during dialog.
- Godot Open Dialogue by J. Sena
- I haven't personally looked at it in-depth, but it seems to have many great features
- Godot-Open-Dialogue-Expansion
- This is a branch of J.Sena's project Godot Open Dialogue and Godot Voice Generator by TNTC-Lab; the ReadMe is a great read
- Godot Dialogue Graph with Json
- A JSON based dialogue system supporting branching and looping dialogue. Although simple, this is what kickstarted the basis of my dialogue system.
- Godot Tutorial - Dialog Box
- A tutorial by HeartBeast on getting text to show up letter-by-letter, which I used when I was learning Godot. If you're learning Godot, I wholeheartedly recommend you check their channel out, especially the Action RPG tutorial!
If you liked this project, or felt this was useful, please leave me a comment and feedback! It would really make my day. Sharing about my dialogue system over social media and getting the word out there would help me immensely too! Thank you!
And, if you ever make a game with this, I'd love a know! Please send me a link of your game so I can support it! <3