I'm chipping away at implementing the dialogue system. It's daunting; sometimes it feels like trying to build a house all at once. Once you start to sort out what the foundation is, what part depends on what other part, etc, a build order starts to become clear and the whole implementation becomes more manageable. If you can sort that out on paper and think through most if not all of the possible issues, implementation is really straightforward.
Some of the key features like choice selection, tracking dialogue states (e.g. remembering how many times you've interacted with that speaker), and speaker tracking are demoed below:
I discussed an ambient dialogue system in a previous post and made some headway on implementing it. The off-screen dialogue box handling needs more work (really janky atm), but I have the dialogue box "blurring" (which fuzzes dialogue boxes as you get further from then, to mimic those voices becoming harder to hear) more or less working.
I had to compromise a bit though. I originally envisioned a gaussian blur effect, where at sufficient distances the dialogue boxes were basically smeared into nothingness. But blurring individual UI element is really complicated. It looked like the only approach was to setup separate viewports for each dialogue box, render those to textures, and then apply a blur shader to those textures. Way too complicated.
Here's the current implementation of dialogue "blurring". As the player gets further from the speakers, the dialogue boxes scale down and become transparent. It needs some tweaking, e.g. the transparency change looks awkward as a linear function, maybe should be using squared distance to feel more organic. But I think this works well as a general approach. This also means that distant dialogue takes up less screen space, so there'll be less clutter.
Here's the handling of off-screen/ambient dialogue. I ended overcomplicating it, spending too much time trying to implement this unnecessarily complicated version, then found that the simpler approach worked better anyways (just clamping off-screen dialogue boxes to screen space). There was some weirdness that needed fixing—basically, off-screen objects in perspective cameras are positioned counterintuitively, so the y-positioning of the dialogue boxes can look unexpected. The most noticeable case is when off-screen dialogue boxes are positioned at the top the screen for things that are behind the camera. It feels more "natural" to have those at the bottom of the screen; so there's a small snippet that ensures that's the case.
The other feature, which is also a bit janky right now, is interrupting ongoing NPC dialogue. Discussions where the player isn't involved, i.e. among a group of only NPCs, advance automatically. If the player enters the vicinity of any of the NPCs involved in that discussion, and the player can speak with at least one of those NPCs, they will pause their discussion and address the player. If the player leaves the vicinity, they resume their discussion from wherever they left off.
There's a lot to tweak here, like timing around the discussion pausing and resuming, checking for race conditions (always a possibility when timers are involved), and figuring out how best to handle the lead-in/lead-out snippets (here: "Do you need something?" when the player interrupts and "What was I saying..." when the discussion resumes).
Aside from cleaning up the implementations of these features, I'm mostly finished with this first pass at the dialogue system. Still many things to figure out about how dialogue is best triggered and how it should be associated with entities and so on. No doubt things will need fixing and I'll want to do things the system doesn't support as-is. And the tools will also change; I'm already finding pain points with the dialogue editor that need improving.
The next step is to start reviewing all of my notes for the game's world and story and start putting together a more concrete draft/design document. That'll help me figure out what other key mechanic systems are required.