Hi yall! I would like to show a project of mine i’ve been working on and off for a little over three years now. Not a game, but a game making tool. I present to you - Dialogue Editor, a tool for writing branching dialogues! (I did not care to come up with a quippy name, sorry. Maybe if i ever open it to the public i’ll rebrand). Made in Godot, to be used with Godot (initially).
Part 1. Research
I love bioware rpgs. I love dialogue options. I want to make games that are filled to the brim with player expression and reactivity. I need a tool that facilitates that.
Now, dialogue in games is well-troden territory, so firstly i explored existing offerings. Those included Twine, Ink, Yarn Spinner, Ren’Py, Articy (used in Disco Elysium), Chat Mapper, Dialogic by Emilio Coppola Narrat by Liana Pigeot, Dialogue Designer by radmatt, RPG Maker, SRPG Studio, Dragon Age Origins Toolkit, Divinity Original Sin 2 Toolkit, and various Unity and Unreal plugins.
My requirements were:
- Works with Godot.
- Graph-based. The two major paradigms i saw were 1) graphs with interconnected nodes of text and 2) linear text with jump-to bookmarks. Both have their strengths and weaknesses, but i figured graph-based suited my purposes better.
- Flexible. I would like to be able to use it for all sorts of games with all sorts of UIs, dynamic characters, and what not.
- Pleasant to use.
Nothing i found fit all of those, i had to make a tool that fit my hand myself after all. The edior i liked most was the one Obsidian made for themselves, shown off in a briliant GDC talk by Carrie Patel and David Szymczyk. The Divinity one was a close second, if only because they are quite similar. And so, armed with a youtube video as reference, i set out.
As a side note, it is worth saying that dialogue trees, which all these tools essentially boil down to, are not the only possible way to do non-linear narrative. I highly recommend Emily Short’s excellent blog in general, and specifically her posts about quality-based story structures and storylets. As well as a Valve GDC talk about their contextual dialogue system in left 4 dead, which is essentially a storylet system too.
Part 2. Showcase
And three odd years later here’s what i have on my hands.
Explanation of the different node types if you're interested
The three bread and butter nodes are:
- Hear Node - the regular text node. Be it anything an npc says, narration, or the full version of a dialogue option your character says out loud, like in mass effect or later dragon ages or fallout 4 or witcher or cyberpunk or greedfall you get the idea.
- Say Node - dialogue options presented to the player as a list
- See Node - cutscene direction nodes, their text is hidden in the final gameplay. Borrowed that one from a Baldur’s Gate 3 cinematics GDC talk by Jason Latino
Additionally two special nodes are:
- Root Node - dialogue starting point. I’ve seen some people also use an Dialogue End node, but it is imo redundant.
- Reference Node - a “link” to a different node, which allows loops, merging of branches, etc. It can either reference a node itself, or it’s children (borrowed that functionality from the Divinity Toolkit)
The playback order is the same as in the Obsidian editor, you can watch the linked gdc talk for the explainer.
A loose pile of features:
- Auto-placement of nodes. No constant re-arranging of nodes, no manual connecting of one node to another.
- Keyboard navigation. you can see the mouse cursor in that gif, it aint moving much. i don’t have hotkeys for everything yet, but just being able to move around with the arrows / zoom to a particular node / enter and exit text editing is sooo good.
- Undo/redo system. That one is so vital oh my god.
- Search nodes by text.
- Folding/unfolding of branches.
- Simultaneous editing of multiple dialogues in different tabs.
- Condition and action system. Dialogues can share flags, set them, check for them, as well as execute scripts.
- Actors and node tags are also shared between dialogues. You can select which actors are present in the current dialogue.
- Separation of editing-time and play-time data. this allows doing things like generic dialogues between Character A and Character B, with actual identities of A and B provided at runtime by game logic.
- Settings! Customizable color-coding, node spacing, optional auto-saving
I tried to make it flexible enough to allow all sorts of in-game presentations. As an exersice i’ve re-created the Disco Elysium column diaogue. Fun fact, while doing this i had the game opened for reference and wanted to see how they handled a particular edge case. Turns out, they didn’t! It was bugged.
Disco Elysium bug
Part 3. Regrets
The biggest mistake of this project by far was envisioning it as a Godot extension. When i first discovered Godot and made it my engine of choice i was dazzled by the idea of godot editor running on godot itself, and how you can use godot to make plugins for godot. And also how godot is an all in one solution, you can edit levels AND write code in one program! So wouldn’t it be cool to write dialogue in that same program! It was a fundamental design decision i made at the very start and it has done nothing but bite me in the ass ever since.
Here’s how it shook up. The pros:
- I can use godot’s file explorer to create and edit resource files. which means i don’t need to implement my own dialog windows for settings and some supporting file creation. saved myself like two days of work!
- I don’t need to fuck with file formats, saving and loading, i can just use godot’s resources
- I don’t need to have multiple programs opened, everything lives inside of godot. Minimalistic!
The cons:
- Biggest one by far: sometimes code works differently when you run it as an executable vs a plugin. you can debug an executable. you can not debug a plugin. so if something works in debug but then doesn’t work when used as an actual plugin, you’re fucked! the most common case was me forgetting the ‘tool’ keyword at the top of the script, but it was also the most trivial to catch and fix. but some of those were real mind fuckers. Files didn’t save, files got corrupted, files didn’t load properly, plugin code didn’t get loaded properly, it’s a horror show in there
- Some godot hotkeys could not be disabled or overriden (at least i couldn’t figure out how). So you would accidentally add new nodes to the opened scene even though you were in the dialogue editor tab, not the scene editor tab.
- Having the editor be embedded into the engine means i’m tied to that version of the engine. When i started this project, the latest version of Godot was 3.4. Currently the latest version of Godot is 4.3. I intend to use this tool for at least the rest of my life. So if i want to use some cool new engine feature for the actual game that i’m supposedly making with the tool, i need to port the editor to the newer version of godot. Just porting from 3.4 to 3.5 broke some things. I can’t even begin to imagine how many things will break if i port to godot 4.
- I’m not even using godot to make a game right now!!! I’m making a game for the playdate, rolling my custom engine in freaking lua!!! all this Native Godot Integration is completely irrelevant!!!
- Oh and because i’m using a completely different engine, turns out, i DO need to fuck with file formats, saving and loading! Strike that pro #2 frome the record! Also, godot’s resource files SUCK. Incremental counter ids are totally unusable with version control. So many a corrupted dialogue file. Had to write my own unique id generator.
- And to open the dialogue editor, i now need to keep the entire godot open, even though i don’t use any of it for development. instead of having less programs opened, i now have extraneous programs opened! Not minimalistic at all! Strike that pro #3 from the record as well.
So yeah, after three years of banging my head against a wall for what amounted to no reason at all, i have finally decided to abandon my aspirations of making it a godot plugin, and now the editor will (at some point) become a standalone program.
Part 4. Future
At this point i’ve largely moved on from working on the editor to working on an actual game using it. There is still plenty of work to be done, like moving away from the plugin paradigm, polishing out the jank, stomping out minor bugs. It is roughly feature-complete, the big remaining one is localization tables. Another cool feature i want is nested dialogues: having nodes that contain full sub-dialogues inside of them. This one is not essential and requires a lot of ui work, so it’s kept on ice for now.
I’m not sure if i want to make the editor available to the public. Doing so would require writing documentation, lots of polishing, timely bug fixing, etc. And i want to spend my limited time on making games, not maintaining tools for making games. Additionaly, i’m not sure anyone would even want to use it. It is not nearly plug-and-play enough for people who don’t want to futz with code. And people who do would probably find it too opinionated (three years later some of those opinions even i don’t agree with!) and would rather make something from scratch themselves.
So for now it will remain used by just me and a couple friends. It can be available upon request, but keep in mind its semi-finished state. Maybe in a couple more years.
Part 5. Lessons Learned
- Copying (or more specifically re-creating) other people’s work is great! Looking at other people’s work under a microscope, figuring out how to make it yourself, improving things you didn’t like about the reference along the way. It will absolutely make you a better craftsperson.
- Having tools be separate specialized programs is good actually. It takes a little bit more upfront work, but results in less dependency, less maintenance, and more flexibility. You can have yourself a separate level editor, a separate dialogue editor, a separate database editor, a separate code editor, and be better off for it.
- Tale as old as time, i got stuck in the tool making stage, instead of the tool using stage. The editor was already usable like two years ago. But also it is now just so much more pleasant to use. Idk. I’ll report to you on this in like two to three years when i finish a game with it and tell you if it was worth it.
And this concludes my show-and-tell, thanks for reading!