Composite Pattern in Unity?

I’m working on an assignment where I need to implement an example of the Composite Design Pattern in Unity with a dialog tree that has a depth of at least 5 levels. So the example I am supposed to use is a non-player character talking. The composite will contain what the NPC says as well as other options for the NPC, and the leaf will contain just what the NPC says. I don’t have a reference to go off of and the internet is our only resource, so as I have never worked with this design pattern before, I am having a lot of trouble figuring out how this is supposed to work with the other examples that are out there. I feel that I have a good foundation down (which I will paste below), but what I was wanting to do was have the user press a button to keep saying sentences (composite) or have them press a button to say the last sentence (leaf). If anyone could help me figure this out I would greatly appreciate it.

Component

public interface IComponent
{
    void Talk();
}

Composite

public class Composite : IComponent
{
    private List<IComponent> components;

    public void Setup()
    {
        components = new List<IComponent>();
    }

    public void Add(IComponent component)
    {
        components.Add(component);
    }

    public void Remove(IComponent component)
    {
        components.Remove(component);
    }

    public void Talk()
    {
        foreach (var childComponent in components)
        {
            childComponent.Talk();
        }
    }
}

Leaf

public class Leaf : IComponent
{

    public void Talk()
    {
        Console.WriteLine("Talking...");  // Not sure about this
    }
}

Main Script for Buttons

public class MainButtons : MonoBehaviour
{
    public void ButtonOnePressed()
    {
        var compositeTalk = new Composite();

        compositeTalk.Add(new Leaf());

        compositeTalk.Talk();
    }
}
  1. I’m going to point out that the component design pattern implemented in Unity is technically a composite design pattern… with some minor tweaks.

  2. Could you describe the problem as given by your instructor. We can’t answer the question for you, but at least then we know what your instructor is asking. This way we’ll be able to give you direction in line with your instructor and not your interpretation of the instructors request.

  3. Try breaking your paragraphs up. Your wall o’ text is difficult to parse since you spend the entire block of text jumping between subjects. Maybe paragraph 1 is the problem, paragraph 2 is how you interpret that problem, paragraph 3 is what you need assistance with… etc.

1 Like

Since it’s an assignment I’m only gonna put some ideas that come to my mind.

First of all and totally unrelated to the pattern itself: the method that handles the button only creates an object that will be ready for garbage collection after the method returns. Not sure if that’s desired in your case.

Secondly, there’s a flaw in the way you execute the talking. I guess you only want to output specificly chosen options. Currently you traverse the whole dialogue tree as you keep calling Talk() on all children.

Now some implementation ideas, i don’t know whether or not they match the conditions and instructions.

Easiest first: I’d probably create a script with such an IComposite variable.

On initialization of that script (Awake, Start or a dialogue-start-event), I’d completely build up the dialogue tree. Therefore, a composite and the leafs should offer a way to set the current text. This can be achieved with a constructor or a setter. If you use a setter which is probably more preferable, the interface should clearly provide that one. If you use the constructor (or both), you can also throw in an abstract base class that enforces a string as parameter and does not offer a default one.

Next, there also needs to be an option to navigate through the tree. Since it’s a tree, you are probably supposed to offer more than one “next option” (otherwise it would be a boring chain-like conversation with no options) and need to have an integer or so that indicates which option to navigate to in the next step. The implementation is up to you, just note that the dialogue is finished if the current node is either a composite with no IComponent in it’s list, or a Leaf which simply doesn’t have any further ‘children’. But I’d rather make sure to always end with a leaf in each branch.

So far so good. I know you currently only need the NPC to talk, but if you want to add user interaction for each step in the dialogue or a waiting time instead of throwing the whole dialogue into the console within one frame, you may want to find a way to keep track of the current IComposite in order to access it on a later point in time or when an event has been raised (such as a button click).
2 simple ideas for that, implementation is up to you: An IComposite return value for the Talk() method which will be used to re-assign the script variable that I have mentioned above, or a variable on that script to keep track. (Depends on use case)