World Eater - Dialog system
Inleiding
In World Eater speelt interactie met de speler een belangrijke rol. Om deze interactie naar een hoger niveau te tillen,
heb ik een flexibel en schaalbaar dialog system ontwikkeld. Dit systeem biedt ondersteuning voor branching dialogs,
callbacks voor custom code, afbeeldingen, geluiden en dynamische teksteffecten.
In deze blog deel ik mijn aanpak en de belangrijkste features van dit systeem.
Mijn focus lag op het ontwerpen van een oplossing die gebruiksvriendelijk is voor developers.
Ontwerp
Het ontwerp van het dialog system is simpel en consistent gehouden, met een focus op leesbaarheid en een futuristische uitstraling die past bij het ruimtethema van de game:
UI Design: Donkere doorzichtige achtergronden met afgeronde hoeken en contrasterende lichte tekst. Een afbeelding aan de linkerkant, tekst aan de rechterkant en interactieopties rechtsonder.
Interactie: Opties vergroten wanneer de muis erover beweegt om interactie intuïtief te maken.
Deze visuele keuzes zorgen niet alleen voor een prettige gebruikerservaring, maar maken het ook eenvoudig om notificaties en dialogen visueel op elkaar af te stemmen.

Branching
Een van de kernfeatures is de ondersteuning voor branching dialogs. Hiermee kunnen spelers keuzes maken die invloed hebben op het verloop van het spel. Denk aan scenario's zoals een winkel waarin spelers power-ups kopen, een levelselector of een game-over-menu.
De branching werkt via een class genaamd DialogOption, waarin verschillende helper classes zoals SimpleEndDialogOption en SimpleRedirectDialogOption standaardinstellingen bieden. Dit bespaart tijd en minimaliseert foutgevoeligheid. Dankzij deze structuur kunnen developers met minimale code complexe aftakkingen bouwen.
Voorbeeld: Een dialoog waarin een speler kan kiezen:
Doorgaan naar een nieuwe conversatie.
Of stoppen, waarmee de dialoog beëindigd wordt.

Developer experience
Een gebruiksvriendelijke developer experience (DX) stond centraal tijdens de ontwikkeling van het dialog system. Om dit te bereiken, heb ik een reeks helper classes en een duidelijke structuur opgezet:
Classes voor snelle implementatie:
BaseDialog: De meest flexibele klasse, geschikt voor complexe dialogen.
SimpleContinuingDialog en SimpleEndingDialog: Minimalistische classes voor standaarddialogen.
Custom code support:
Door virtual methods in BaseDialog te overriden, kunnen developers eenvoudig unieke functies toevoegen bij het starten of beëindigen van een dialoog.
DialogSound Class:
Geluid en muziek worden toegevoegd via Unity’s AudioSource, met parameters zoals volume, looping en bestandsnaam. Hierdoor kan elke dialoog worden verrijkt met audiofeedback.
De impact hiervan: Met deze structuur kunnen developers snel en efficiënt dialogen bouwen zonder zich bezig te houden met technische details, wat iteraties versnelt en de productiviteit van teams verhoogt.

Hier zie je de BaseDialog class die gebruikt wordt voor alle dialogs.
Rich text & custom effects
Unity's UI toolkit heeft support voor Rich Text, dus ik heb dit gebruikt om simpele effecten zoals
gekleurde en schuin-gedrukte tekst toe te voegen aan de dialog system.
Deze kunnen ingevoerd worden in een string door middel van tags die een beetje lijken op HTML.
Zo wordt bijvoorbeeld de onderstaande tekst omgetoverd tot "Hello, world."
<i>Hello</i>, <b>world</b>
Maar eigenlijk wilden we nog meer effecten toevoegen aan de dialog system om de tekst meer leven te geven. Ik heb besloten deze effecten toe te voegen: Regenboogkleurige, golvende, op en neergaande, schuddende en draaiende tekst. Ten slotte heb ik ook nog wat opties om tekst groter en kleiner te maken toegevoegd als tekst effect.
Deze custom tekst effecten werden samen gevoegd in één C# enum.

Deze enum die DialogTextEffects heet,
kan gebruikt worden bij het aanmaken van een nieuwe dialog om één of meer effecten toe te voegen.
Niet alle effecten werken met elkaar vanwege de manier waarop ze achter de schermen geimplementeerd zijn,
veel wel.
Hieronder zie je een voorbeeld van een dialog waar een regenboog effect wordt gebruikt.
Het regenboog effect is een van de weinige effecten waar ook een "target" string aan toegevoegd kan worden.
In dit geval is dat "space dust".

Het resultaat van deze instellingen is een zin met enkele regenboogkleurige woorden. Hier is een voorbeeld van een dialog uit het spel:

De implementatie van de verschillende effecten bevinden zich in de DialogSystemUI class.
In de CreateDialogElement method wordt door middel van een foreach loop en een switch case bepaald welke effecten worden toegepast.

Alle effecten behalve de tekstgroottes worden toegepast door middel can Unity Coroutines die elke frame een IEnumerator functie aanroepen.
Deze functies nemen de Label (het tekstvak) en voeren het effect met een aantal parameters er op uit.

In dit geval wordt de positie (offset) van het tekstvak berekent door middel van willekeurige getallen,
waardoor de speler de illusie krijgt dat de tekst schudt.
Hieronder is het effect te zien dat de bovenstaande ShakeEffect method produceert.

Soepel afwisselen van berichten
Om berichten soepel over te laten gaan, heb ik een fade-out en fade-in animatie toegevoegd via Unity’s UI Toolkit. Dit creëert een vloeiende overgang en geeft een visuele indicatie van het einde van een bericht, wat de immersie van de speler versterkt.
Technische uitdaging: Het balanceren van animaties en interactie zonder vertragingen voor de speler. Dit heb ik opgelost door een cooldownmechanisme te implementeren dat parallel draait aan de animaties.

Dit is het einde van deze developer blog. Dankjewel voor het lezen!