NullReferenceException When Using Composite Design Pattern

So I’m trying to make a simple dialogue tree in the form of a composite design pattern, where each member of the hierarchy has basically the same customizable properties, in this case, a question and two options. In Unity, I’m trying to assign the question to a textbox and each option into a button. When you click a button, you go to another level of the tree, or a leaf. For whatever reason, I’m getting the null reference exception error and its pointing to this line. I’ll try my best to answer any further questions.

    Textbox.GetComponent<Text>().text = question;

It might be something simple I can fix, but I’m not really sure where to look right now. If anyone could help me in the right direction, I would very much appreciate it. Thank you. Here is my script for the levels in the composite pattern.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;


public class Composite : MonoBehaviour {


    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 class Level
    {
        public static Text Textbox;
        public static Text Button1;
        public static Text 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;


            Textbox.GetComponent<Text>().text = Question;
            Button1.GetComponent<Text>().text = OptionA;
            Button2.GetComponent<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;
        }

    }

    }

Initializer Script

public class Initializer : MonoBehaviour {

public Text Textbox;
public Text Button1;
public Text Button2;

void Awake()
{
    Composite.Level.Textbox = this.Textbox;
    Composite.Level.Button1 = this.Button1;
    Composite.Level.Button2 = this.Button2;
}

}

Either Textbox variable is null, or GetComponent () returns null.

There are several things which doesn’t make any sense. First of all you declared the 3 Text variables as static variables. That means the Level class has only one instance of those variables. This may be intended, however it makes no sense to set the text of those inside the constructor of your Level class since only the last constructed object will actually take effect.

The next thing is your GetComponent calls are completely unnecessary since your variables do already reference Text components. So instead of

Textbox.GetComponent<Text>().text = Question; you could just do:

Textbox.text = Question;

Finally you seem to mix at least two different usages into one class. You have two constructors but the second does not initialize the levels array. This may also be intended since you want to use that level instance as “leaf node”. However your class has no security / sanity checks. For example the “add” method directly calls levels.Add even though you have cases where levels is no initialized. It may not be a problem in your particular case but it’s just bad design. The usage of a class should be seen as a black box so a user does not necessarily know how the class is implemented.

Currently you just create all those Level instances inside Start but you don’t store them anywhere. When Start is finished all those instances will be up for garbage collection.

It’s not really clear how you want to actually use those classes. However i think it would make more sense to add some kind of “Show” or “Activate” method which does the setting of the stored question and answers to the UI Texts.

I would also strongly recommend to rename most of your classes and variables to be more descriptive. Your “Level” doesn’t seem to represent a “Level” but more like a dialog line / dialog node.