- Home /
How to Create a Dialogue Tree?
Hi. So I have this program set up where I want to display a question and two options, and if you click one option, you either go to another level of the tree or a leaf. I want to use the composite design pattern to make separate level instances, each with different paremeters for one question and two options and add them together into a list. What I'm stuck on is how do I start at the first level and traverse down the tree? It seems like no matter what I do, it only displays the last level parameters added to the list. If anyone could shoot some ideas, I would appreciate it. Thank you.
public class Level : MonoBehaviour {
bool button1Pressed;
bool button2Pressed;
private void Start()
{
Level Level1 = new Level("Hello", "Hi", "Shut Up");
Level leaf1 = new Level("Don't be Rude");
Level Level2 = new Level("What you Doing?", "Not Much", "None of your Business");
Level leaf2 = new Level("Well Excuuuuse Me");
Level Level3 = new Level("Can I do that too?", "Sure", "Go Away");
Level leaf3 = new Level("Fine. Be a Jerk");
Level Level4 = new Level("This is boring, can we do something else?", "Why not?", "You're boring");
Level leaf4 = new Level("I'll go be boring somewhere else");
Level Level5 = new Level("You want ice cream?", "Sounds Good", "I'm allergic");
Level leaf5 = new Level("ok.......");
Level leaf = new Level("I Want Chocolate");
Level1.add(Level1);
Level1.add(leaf1);
Level2.add(Level3);
Level2.add(leaf2);
Level3.add(Level4);
Level3.add(leaf3);
Level4.add(Level5);
Level4.add(leaf4);
Level5.add(leaf5);
Level5.add(leaf);
}
public static Text Textbox;
public static Button Button1;
public static Button Button2;
public string OptionA;
public string OptionB;
public string Question;
public string Leaf;
private List<Level> levels;
public Level(string question, string optionA, string optionB)
{
this.Question = question;
this.OptionA = optionA;
this.OptionB = optionB;
GameObject.FindGameObjectWithTag("Level").GetComponentInChildren<Text>().text = Question;
GameObject.FindGameObjectWithTag("OptionA").GetComponentInChildren<Text>().text = OptionA;
GameObject.FindGameObjectWithTag("OptionB").GetComponentInChildren<Text>().text = OptionB;
levels = new List<Level>();
}
public Level(string leaf)
{
this.Leaf = leaf;
Textbox.text = leaf;
}
public void add(Level lvl)
{
levels.Add(lvl);
}
public List<Level> getLevels()
{
return levels;
}
public void Button1Pressed()
{
}
public void Button2Pressed()
{
}
}
Answer by Stratosome · Jul 16, 2018 at 07:51 AM
Well, what I'd do for this type of this, it make some kind of linked list thing, except one node could point to many. Kind of like this?
public class Dialogue {
public string text;
public List<string> options = new List<string>();
public Dialogue previous;
public List<Dialogue> next = new List<Dialogue>();
public Dialogue(string text = "Default text") {
this.text = text;
}
public void AddOption(string option, Dialogue dialogueIfSelected) {
if (option != "" && dialogueIfSelected != null) {
options.Add(option); // Add text option
next.Add(dialogueIfSelected); // Add destination dialogue
}
}
public void RemoveOption(int index) {
if (index > 0 && index < next.Count) {
options.RemoveAt(index); // Remove text option
next.RemoveAt(index); // Remove destination dialogue
}
}
public void SelectOption(int index) {
// Validate index
// ...
// Grab next dialogue
Dialogue newDialogue = next[index];
// Display new dialogue
// ...
}
}
You'd then have to initialize a bunch of Dialogue objects and connect them all to form your full dialogue, but after that is done, progressing through it would be easy. Just display the initial Dialogue, and then keep selecting a new option and displaying the new one. If this wasn't quite what you were going for, sorry, I tried. :P
$$anonymous$$aking the class extend $$anonymous$$onoBehaviour like you have would make this kind of difficult to do I think. This seems like something that would be best done with just basic classes and such.
Answer by Harinezumi · Jul 16, 2018 at 08:11 AM
Interesting question! I don't have an exact solution, but I will try to direct you in the right direction.
First of all, you must never instantiate a class that derives from MonoBehaviour
with new
. Unity does internal magic with classes that derive from MonoBehaviour
, and if you instantiate it directly with new
, it cannot do that and memory management will get messed up. So always use Instantiate()
for these classes... or consider an alternative.
The alternatives are either a "regular" class (not deriving from MonoBehaviour
), or a class derived from ScriptableObject
. In both cases these classes would only hold your conversation data, and you would need a separate class to traverse this data. But this is a good thing, you should always try to separate your data (Model), the display of it (View), and the logic (Control). One way of doing that is the MVC pattern.
So you could have Level
as data object, and a ConversationControl
class that uses the data from each Level
to show the question and the options to the user, then based on the input, go to the next level, and repeat... the display should be a separate class that has the references to the UI elements.
So what's the difference between using a regular class and a ScriptableObject
? The first is easier to set up, but you cannot easily set it values from the Editor, while the second is more complicated, but Unity supports saving them into scriptable object assets, which are basically prefabs for data, easily configurable from the Editor. This is a huge topic in itself, but there are some good videos about it. Check out this (long) talk about why they are great and how to use them, or this short, but less amazing tutorial (probably they work best one after the other).
One more thing about ScriptableObject
s: as with MonoBehaviour
, you must never instantiate them with new
, you must use ScriptableObject.CreateInstance<T>()
.
I hope it is clear what I mean and will be useful answer to you. Feel free to ask questions in comments, I'll try my best to answer them!
Your answer
Follow this Question
Related Questions
Dialouge isnt working 1 Answer
Polymorphism for decisions in a dialogue editor 1 Answer
Spaw dynamic (unregistered) object on network (UNET) 0 Answers
Vuforia and OpenGL 3 0 Answers