Dialogue System Tutorial?

Hi all,

I’m looking for a tutorial for creating a dialogue system with Unity’s new UI, preferably with C#. I’m competent enough to slap something together at this point, but I’d like to learn the proper way to do it. Thanks!

No one?

Maybe people are finding it to be too broad a topic to do justice in a simple reply. For example, how are you going to manage the data (e.g., the conversation trees)? XML? ScriptableObject? Import from a tool like articy:draft?

How will that data map interactively to UI elements?

How will you link player responses to other gameplay data?

Will you also need to manage the scene, such as moving the camera to look at each character as they deliver a line? Do you need to integrate lipsync or audio?

Here are some thoughts on the Unity UI-specific part:

You’ll probably have at least two panels, one for delivering lines of text, and another to present a menu of the player’s response choices (assuming you’re talking about traditional menu-response branching conversations).

For the text panel, you could use a single screen space panel with a Text element, or you could use world space panels on each character – for example, to implement speech bubbles above their heads.

For the response menu, consider using a ScrollRect. Make the scroll content a Vertical Layout Group. Set up one “template” button. When building a menu, instantiate as many copies of this template as you need, and add them to the scroll content. I mean “instantiate” in a general sense; you could call Instantiate() or you could manage them in a reusable pool.

If you want to implement something like a BioWare “dialogue wheel,” you won’t use a ScrollRect. Instead, you’ll define each button at design time. You’ll probably also need to add data to each response that specifies which button it’s assigned to. Usually one button position is reserved for “good” responses, another for “evil” responses, etc.

Since UI elements are regular GameObjects, it’s easy to apply animations to them. For example, you can slide the response menu on and off the screen, or fade speech bubbles in and out. Just add an Animator and call Play() with the appropriate state name.

Your design will necessarily be a little different if you intend to make a different type of dialogue system, such as one using icon-based “verbs” or a freeform text input interface.

4 Likes

Thanks for the response, Tony. Sorry for not being more specific with my question.

I’m developing a 2D game - my first, so I’m trying to keep my ambition reigned in and err towards simplicity. I envision a panel with NPC dialogue text and then 2-4 buttons below with player responses, which when pressed of course result in a response from the NPC. Mostly I’d like to see something on the scripting side (C#) - how best to handle a conversation tree.

Thanks again.

I like the old “divide and conquer” approach. You might want to split this into two or three parts that talk with each other but are responsible for their own individual tasks. Perhaps a division like this:

1. Data: Figure out how you’re going to store the conversation tree (NPC dialogue text and player responses). You could do this any number of ways. The easiest might be to store a conversation in a MonoBehaviour script so you can edit it in the inspector.

public class Conversation : MonoBehaviour {

    [System.Serializable]
    public class Node {
        public string dialogueText;
        public Node[] responses;
    }

    public Node startNode;
}

2. GUI: Given NPC dialogue text and an array of player responses, show them in a Unity UI panel. You could write a MonoBehaviour script that has public variables for the panel, dialogue text, and an array of buttons. If there are fewer responses than buttons, temporarily deactivate the unused buttons. When clicked, the buttons should send an event back to progress the conversation.

public class ConversationGUI : MonoBehaviour {
    public UnityEngine.UI.Text npcDialogueText;
    public UnityEngine.UI.Button[] playerResponseButtons;
}

3. Runner: Given a Conversation and ConversationGUI, run the conversation. This component can keep track of where the player is in the conversation, feed this to the GUI, and handle responses back from the GUI.

In software engineering terms, Data, GUI, and Runner use the Model-View-Controller (MVC) pattern.

4 Likes
1 Like

Thanks Tony. That’s along the lines of what I was thinking.

And thanks rakkarage. I’ll take a look at those videos.

Rakkarage, those vids were exactly what I was looking for. Rock on.

I just tried putting this in - interestingly, it seems like that data structure triggers an error about the Serialization depth limit being exceeded:

Serialization depth limit exceeded at ‘Node’. There may be an object composition cycle in one or more of your serialized classes.

I guess it makes sense why it’s doing that, but any thoughts on how to get around that error?

I think Unity can’t serialize past 7 levels, so you’ll have to flatten it out or spread it across child GameObjects.

I don’t exactly recall why you didn’t want to put the conversation in a separate data structure such as a ScriptableObject, other than perhaps for simplicity.

To stick with the current approach, flattening it out may be easiest. One way is to make each node a MonoBehaviour:

public class ConversationNode : MonoBehaviour {
    public string dialogueText;
    public ConversationNode[] responses;
}

Add a ConversationNode for each line in the conversation. String them together in the responses[ ] array. Another nice thing about this is that you can loop back and/or re-use nodes.

Then add another MonoBehaviour that lets you specify which is the start node:

public class Conversation : MonoBehaviour {
    public ConversationNode startNode;
}

As an alternative, look into using XML instead of the inspector, or options on the Asset Store such as Parley (there’s a free edition) or of course the Dialogue System for Unity.

Yeah, I was thinking about XML - BTW, I’m not the original poster - I just happened upon this thread google searching for NPC dialog systems and tried out the code. I love the look of your Dialogue system too. I may just go ahead and use that. Thanks!

Oops, sorry, missed that. I’m glad you pointed out the serialization depth issue though in case others run into a similar issue.

Hi Tony,

A quick question. I am trying to set up variables and Actor´s property from C# code, without success following the instructions on your website. Could you please help me with this? As a test I tried the following;

    void Start ()
    {
       
        DialogueLua.SetVariable("PlayerName", "test");
        DialogueLua.SetActorField ("Player", "PlayerName", "test");
        DialogueLua.SetActorField ("Player", "Name", "test2");


    }

and I set up both the Actor (Player) and Variable (PlayerName) on the Dialogue Manager editor. Still when I start the game, neither the variable PlayerName or the Actor´s field change to what I want. The script is attached to an active gameobject and all other functions on that script run well, except the above code which seem to be doing nothing.

Could you please help me with this? what might be wrong?

Thank you in advance,
Alex.

Hi @alexhapki - Since this question is related to the Dialogue System for Unity, I replied here.

If you’re still looking into a dialogue system, I have one released on the store, it’s only $5:). Simple Dialogue System | GUI Tools | Unity Asset Store

Hello, how can I activate game objects in scene when specific dialogue is selected?

For example I talk to an NPC and I can say yes or no. Yes will activate a guide arrow next to him and no will activate a trap door under the player

I don’t know if you’re asking specifically about the Dialogue System for Unity (since it was linked above). If so, just drag the GameObject into the dialogue entry node’s Sequence field. This will add a SetActive() sequencer command to set it active or inactive.

1 Like

Thanks for the reply! And yes I was asking about the Dialogue System For Unity :slight_smile:

When dragging my disabled gameobject into the “sequencer” field on that node I get “Camera(default,Scene 3 )” which doesnt seem to activate the gameobject. I tried changing it to SetActive(default,Scene 3 )" but that does not seem to work either

You can customize the action that’s added when you drag and drop a GameObject onto the Sequence field. (Select “+” > GameObject Drag-n-Drop)

To activate the GameObject named "Scene 3 ":

  1. Rename the GameObject to “Scene 3” without a space at the end. Otherwise it may cause confusion.

  2. Set the sequencer command to: SetActive(Scene 3)