Big Ol’ Disclaimer:
This approach is very specific to my game and the limitations I have to work around. Most notably, it is tied to my dialogue system which is a third party asset called, er, Dialogue System which is $65 or your regional equivalent. Still, I hope that sharing my process proves to be useful, and possibly enlightening.
My current game project is set on the internet of 2009, and what would that landscape be without MSN Messenger. When I started this project, I didn’t even know what to search to begin building this feature. “How to make a fake chat”? “How to make a messenger client”? “How to make a fake text message system?”. It’s something that’s been done a fair few times and is an instantly recognizable feature, but lacks the widespread appeal of, say, a health bar.
Several pages of search results about MMO style chat clients later, I had some sort of a starting point. For version 0.0.0.0.1 of this thing, I used Fungus. Built for visual novels and point and click games, its focus on narrative made me give it a shot. Following this guide I found, I had a bare bones MSN knockoff in a couple of hours.
I was pleased that I had something up and running…but it did not scale well at all.
The chat box contained five Fungus text boxes for each participant – five for the NPC and five for the player. When I new line of text was typed all of the existing text was shifted up into the text box above it. Clever, but not the most elegant thing. It also meant that for every new line of text I had to put together this big block of instructions.
Yeah, it was no fun. Fungus is a great free tool, but bending it this out of shape meant that the relationship wasn’t going to last. It’s not you Fungus, it’s me.
I knew I had to build a more robust system that could scale, and preferably had an external text editor for the writing bit of constructing a narrative. After a day or two of research, I decided to give Dialogue System a try. Now, I find the asset itself to be extremely bloated, containing a lot of 3D models and plugins that 90% of users aren’t going to need or want. But hidden deep in the ‘extras’ section of the documentation I found a demo scene for an MSN-like chat client, and that gave me the confidence to try it out.
Dialogue System has quite a simple core. It handles Player Character dialogue, subtitles and choices , NPC dialogue and subtitles, and a couple of UI elements surrounding those two things. For my chat client, I didn’t need the avatar images or the timer. Or even dialogue!
All of these elements are all controlled by a Dialogue Manager, which holds conversations and characters and variables and all manner of things. Like I said, this tool is huge.
Being an artist, I was first concerned with getting everything to look right. I find that I work much better when I have a halfway decent art pass to look at. Dialogue System’s UI elements are pretty flexible. They can be moved around, re-ordered, re-themed with no issue, they just need to be correctly referenced in the script that run everything (more on that soon).
My chat client is made of those same elements from the last screenshot, just jumbled up a bit.
So, now that I have it looking nice, it’s time for the stuff that’s making it tick. The demo MSN messaging scene that Dialogue Manager came with was my base for all of this, but I changed a whole lot. The script shown in the Inspector below sits on the chat window itself, and handles the scrolling of the text as new lines are added.
As you can see, it points to each UI element that I laid out earlier. The PC and NPC “subtitles” are used as lines of text in the messenger, and a record is kept which becomes scrollable when it gets too big. The Responses Button gets turned into a list of possible replies at runtime, which are then passed into the record of the conversation.
Dialogue System has a built-in flowchart for crafting conversations, which I found nice and easy to use. It automagically separates out NPC and player lines of dialogue, and is great for visualizing the structure of your narrative. However…it doesn’t scale well. Hello darkness, my old friend.
Dialogue System has several options for external script editors that it supports out of the box. As a single developer working on a game with no budget, the only one that was really viable for me was Ink.
Ink is the open source scripting language created by Inkle, the makers of 80 Days and Sorcery!. It’s a words first, code second kind of language that is written in plain text inside of Inky, the editor (the names are so goddam cute!). I watched a talk by one of Inkle’s founders, Joseph Humfrey, which really cemented my desire to use Ink for this game.
Ink has a unique structure that allows for not only large branching paths and loops, but smaller side detours that quickly fall back into the main story flow. Where node based text editors really fall down, I feel, is in their insistence that every branch must be significant. That’s built into them by design. With Ink, little moments can happen that don’t require a dedicated branching of the narrative, without a big neon sign that says “Alert! Important story diversion here!”. That approach can work for traditional quests or visual novels, but I wanted the chatting in my game to be transient and digressive, taking many small wiggles around the main points of the story.
The other reason I chose Ink was its plain text editor. I struggle to work well when I’m writing things out in nodes or spreadsheets. I like a blank page that I can write all over, to make lists and sections for my thoughts, to have a linear hierarchy that I can tumble down. Ink’s markup is perfect for that type of workflow, even if it has a learning curve. I haven’t gotten to spend much time with Ink yet, so I probably have some of the syntax wrong, but I find it much easier to follow and quicker to write.
So, with an Ink file full of story, I had to get it into the game. Dialogue System has inbuilt Ink support, and can even recognize some special tags within Ink. In the screenshot below you can see each line tagged with which actor is saying it, so it appears as it should in the chat window.
Instead of using the node based system I showed before, a blank Dialogue Manager is used and the Ink file takes over the rest. However, there was one major problem I ran into.
Ink came out of Inkle’s own games, which feature a strong narrative voice. The example files feature three minimum character – the player, an NPC and the story narrator. It’s great for more traditional narratives, but it wasn’t going to work in a one-to-one direct message situation. Adding an Ink file with no changes caused lines of dialogue to repeat themselves as the player *and* the story said the same things.
For days and days I struggled to fix this. I looked over all my chat window code. I dug through code I shouldn’t have had to go near in the depths of Dialogue System. I tried to remove all reference to the narrator character in the Ink plugin scripts (it really didn’t like it when I did that). And in the end, the answer was right there near the documentation.
Ink does let you suppress the repeated text, it just needs to have everything written in the square brackets. I took a few minutes to fix my writing and it worked a charm. Game development: you win some, you lose some, you gain another grey hair or two.
With Ink as my narrative editor and Dialogue System as my chat handling tool, I’ve built a robust, scalable workflow that should see me through the rest of development. There are features I still want to add – notably delays on the NPC replying to you and recording choice outcomes – but I’m happy with the point I’ve gotten it to.
Sometimes you need to admit that a system isn’t working for you and start from scratch again. If the time you’ll save not wrestling with node editors is worth the time you’ll spend setting something else up, go for it. Game development is all about trial, error, informed guesses, hope and the occasional dead end.