Monday, April 5, 2021

The horrors of writing my own conversation system (continued)

So, the elephant in the room is that after more than a year my conversation system still SUCKS. I tried writing a real conversation in my system for the first time in my system as part of the work I have been doing to get my demo running and I nearly went insane. That's a joke obviously, but it wasn't very fun and debugging my mistakes I made in my own system built FOR ME by ME took me hours. I realised pretty fast that it was going to be untenable to just write the conversations directly into the code with my current system like I had sort of assumed I would. Normally, I'm pretty good at ploughing through difficult and tedious work like this, but the time I would have to spend debugging obscure mistakes would quickly burn me out, I can see it. Thing is, of course, I sort of knew this would happen. I wrote about foreseeing this exact issue in an earlier blog when I gleefully talked about how my convo system was all done and working great. It's doubly frustrating because it is very close to working perfectly. The main thing is just that it's unworkable to write the conversations directly into the code. The code becomes too complex and confusing too fast, and it's far too easy to lose track of what I'm even doing. Here's a screenshot of a single response for a conversation fragment for the Demo NPC I was building: 

ahhhhhhhhhhhhhhhhhhhh

It could certainly be worse, but dealing with magic numbers ("priority") in the constructor just isn't great. This drove me to look into libraries that already handle conversations. I have generally avoided libraries for things I thought I could do myself, because I'm doing this to learn after all. Plus, as a programmer working solo, I find it more motivating and consequently faster to work on my own code that I control and understand than spending time learning someone else's code. Lord knows I do plenty of that at work. What makes it fun as a programmer is being able to do things my way, and that's a big part of why this is a fun hobby. But at some point, I guess it's better to let someone else handle the pain. So, I did a search for convo systems for Unity that I could hopefully drop in and replace mine with. There's a bunch of paid ones - but I can't really justify to myself dropping $100 on an overengineered perfect system I would barely use 5% of the features of and have to spend weeks learning - and some cool free ones. I tried out a cool free one called Fluid Dialogue which looked super promising. The system seems very compatible with my own, and had a cool active community and slick in-unity tree/graph convo editor. 


 
The convo system in use (Demo)


But as I started to use it, I came across a fundamental issue. Most convo systems (fluid included) use a sort of "flow" paradigm, where the conversation is mapped like a graph or tree and answering 1 to dialogue A sends you to dialogue B. From the start however, I built my system state based instead, where answering 1 to dialogue A sets a flag that makes the convo manager choose B as the next most relevant conversation to show. This system means my conversations can flow in any direction at any time, and allows me to be extremely complicated with my conversation choice conditions and effects in ways that I plan to use, but also makes it difficult to adapt to the flow based approach. I got halfway through adapting my demo script I had written into the Fluid Dialogue system before I realised that this was a fundamental issue and couldn't be solved with a simple band aid. So sadly, once again I am forced to reconsider fundamental issues with my conversation system as planned. Going forward I think I have 5 options (in decreasing levels of upfront effort):

  1. Build a visual editor or tool for my existing conversation system inside Unity to allow me to work with my existing conversation system more easily
  2. Adapt Fluid Dialogue to work with my system - I assume this means big rewrites of that code
  3. Abandon the state-based conversation plan and go to a flow-based approach instead, using Fluid Dialogue - including a restructure and total rewrite of my planned gameplay and conversations
  4. Carefully write all my conversations/state down in some gigantic document and test the state flow externally somehow, and then simply copy/paste it into my game system
  5. Suck it up and slog through writing all the convos ad hoc in my code
There are more options of course. I came across a markdown-like system called Ink that has Unity integration, but again like most systems and libraries it uses a flow-based format. In the end, it's really going to have to be a choice between rebuilding my system to be flow based, or making it easier for me to write my state based conversations. I'm just not really sure what to do. I've made some inquiries with the Fluid Dialogue community to see what they think, but otherwise I'm going to have to just sleep on it a bit. I'm feeling a little bit like I'm leaning towards either writing a tool for my system or writing all my dialogue externally first (perhaps both?) at the moment. The idea of using my own system has a powerful draw for the reasons I mentioned before, even if it's a siren song...

It's been fun at least to start building interiors out. Note the new chromatic aberration and noise post-processing effects!

It's a shame I know so little about what I'm doing. But this feels like the way I learn. It would be better if I knew someone who knew what they were doing and could get some advice, but without that this seems like the right thing to do (i.e., flounder in the dark). I looked briefly into how Bethesda's convo system worked in their Creation engine through Fallout3/NV's GECK (their system being a big inspiration behind mine) and wasn't surprised to see a monolithic and dense custom interface system masking a hacked upon flow-based system. Reading about NV's development and their recording voice lines basically from day 1 until the development finalised indicated to me that they must have planned out all their dialogue before programming it into the game. I wonder if they did that through some tool that later converted the raw text into game data, or whether they just wrote it all down in gigantic text files and later copied it into the game line by line. This is baseless speculation on my behalf of course, but it gives me hope that if I was careful enough I might be able to just write my entire game's script down in a file and then later copy it into the game line by line... Or that could be a madness inducing dead end. Like I said, I'll have to sleep on it.

Here's a lighthouse sprite I did a little while back

Also I don't want to say too much but the band whose music I was hoping to get to use in the game is interested! They're interested in seeing the demo first before they commit, so that's another reason for me to get it done asap.