Creating a Scriptable Object Based Dialogue System

I recently started work on a new RPG project, of which I knew I’d need to work on a dialogue system for. After implementing this in the form of JSON / internal database, I settled on creating my own handler for the sake of quick implementation and ‘scriptability’™.

One requirement of this system was to have variable responses, blocked either by prerequisites or due to certain events being triggered.

ScriptableObjects are a wonderful way of storing bits of data that you may not necessarily want to be easily editable in your game. The downside of this method over having a large database is that every conversation is its own instance, meaning that instead of one file that can easily be passed off to a localiser for example, each object must be selected and changed manually in the editor.

Setting Up our Dialogue Class

For my project, I wanted to know both the NPC’s ID and name, this could easily be adapted to hold an ID for looking up a sprite in the case of wanting a profile picture during conversations.

I also wanted two additional fields for my responses, these being pre-requisites and triggers. Pre-reqs allow for certain responses to only display if those conditions are met, triggers send out an event to the object that triggered the dialogue (either the player or an NPC).

The ‘next’ field notes which response to show next, I’d recommend using -1 as your default ‘exit’ value.

[System.Serializable]

public class Dialogue : ScriptableObject {

public int npcID;

public string npcName;

public Message[] messages;

}

[System.Serializable]

public class Message {

public string text;

public Response[] responses;

}

[System.Serializable]

public class Response {

public int next;

public string reply;

public string prereq;

public string trigger;

}

Creating Instances

Now for a slightly awkward tidbit; if you want to create an instance of your lovely new class, we can simply right click the script and we’re done! have to create a brand new class and add a new ‘create’ option in our editor. To do this, just add this either as its own script or inside the dialogue script:

[CreateAssetMenu(fileName = “New Dialogue”, menuName =”Dialogue/New Dialogue”)]

public class DialogueData : Dialogue { }

Once you’ve done this, right clicking inside your assets folder and selecting ‘create’ will now bring up a new menu!

Beautiful! Now once the instance is created, I’d recommend folders for each of your rooms to help keep track of conversations. In this example, I’ve created a folder for all of the conversations held in the living room.

Once you have your conversations, you can now start writing your dialogue. Note that you are still able to implement your own markup for these pieces of text as if they were done in a DB format.

Reading the Text

There are many implementations and areas of customisation for reading in the text so I’ll just be covering the bare bones here.

Create a class called TextHandler and add a new public function called LoadDialogue, pass through both the dialogue object so that we can access the data as well as the sender object itself. (This is useful to us if we want to send events to that object)

Additionally, create a variable at the top of the script where we can cache a reference to the dialogue object for use in other functions.

Create another function called LoadText, this will take the index of our ‘next’ dialogue option. We’ll want to call LoadText(0) inside out LoadDialogue option to start off each interaction at its first index.

Here you can access the content of the object by accessing the reference created earlier and using ‘next’ as the index.

Tip: Using a vertical layout group and enabling/disabling the objects will automatically format them to the number of responses you have.

Now that we have our text-complete dialogue objects and TextHandler, we need a way to assign them to each object.

Create a class called Interactable and create a reference for both the TextHandler and Dialogue option. In my case, I added a little floating speech bubble that shows the object is interactable.

You’re all done! You can now start writing dialogues in seconds and customising it to your heart’s content <3

Looking for an active #GameDev community? Join our partnered Discord community, GameDevNetwork! http://discord.gg/gdn