> For the complete documentation index, see [llms.txt](https://saitama-studio.gitbook.io/essential-systems/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://saitama-studio.gitbook.io/essential-systems/systems/dialogue.md).

# Dialogue

In most games, a system for displaying dialogue is essential, whether for NPC conversations, tutorials, or other in-game messages. Here we display a system that helps you create these dialogues easily

<figure><img src="https://3846168334-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FhjeEdzvIH0d5vrHiguxu%2Fuploads%2Fg1KJRI9RLxhQcIo50nBs%2FScreenshot%202025-01-28%20210639.png?alt=media&amp;token=ed89d00a-796b-41df-8872-f7e6576f7648" alt=""><figcaption></figcaption></figure>

You can create a new dialogue by going to `Create/Essentials/Dialogue/Dialogue`. Here we can configure a couple of settings.

<figure><img src="https://3846168334-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FhjeEdzvIH0d5vrHiguxu%2Fuploads%2FtkVu76S8vU0TiyaDquYS%2Fimage.png?alt=media&amp;token=94186702-7082-4f8d-bb94-cbdc226252bd" alt=""><figcaption></figcaption></figure>

The actual dialogue data is what's called the `Header` and the `Description`. To create a full conversation we can create new `Branches`. A `Branch` is a link to another dialogue instance. For example, if we want to transition from dialogue `A` to `B`, we create a new `Branch` and assign dialogue `B` as the `Next` dialogue.&#x20;

For the dialogue to understand which and when it should transition to another branch, we use `Conditions`. A condition can be for example; Done (whenever dialogue has finished), Skip (if a user presses a button) etc. You can create and locate new conditions under the `Create/Essentials/Dialogue/Conditions`.&#x20;

### Conditions

To create a custom condition, we do the following:

```csharp
// This creates a ScriptableObject that is located wherever all the other conditions are
[CreateAssetMenu(fileName = "Test [CONDITION]", menuName = "Essentials/Dialogue/Conditions/Test", order = 0)]
public class TestCondition : Condition // we must extend Condition
{
    // if Evaluate() is NOT overriden, it will return a protected variable called isSatisfied.
    //     we can change this variable wherever we want directly, or call SetTrue() or SetFalse().

    // we don't NEED to override this, only if we want some initilization code
    public override void Init(DialogueManager manager)
    {
        base.Init(manager); // make sure to call the base.Init()
        // do some initialize code
    }
    
    // we don't NEED to override this, only if we want some dispose code
    public override void Dispose()
    {
        base.Init(manager); // usually, we call base.Init() here.
        // do some dispose code
    }
    
    // we don't NEED to override this, only if we want to return something else, rather than isSatisfied
    public override bool Evaluate()
    {
        return // return some code to evaluate.
    }
}
```

For example, to create a skip condition we write:

```csharp
// This creates a ScriptableObject that is located wherever all the other conditions are
[CreateAssetMenu(fileName = "Skip [CONDITION]", menuName = "Essentials/Dialogue/Conditions/Skip", order = 0)]
public class SkipCondition : Condition // we must extend Condition
{
    public override bool Evaluate()
    {
        return Input.GetKeyDown(KeyCode.Space);
    }
}
```

Or, if we just want to create a condition that auto-selects the branch when the dialogue is finished:

```csharp
// This creates a ScriptableObject that is located wherever all the other conditions are
[CreateAssetMenu(fileName = "Done [CONDITION]", menuName = "Essentials/Dialogue/Conditions/Done", order = 0)]
public class DoneCondition : Condition // we must extend Condition
{
    public override void Init(DialogueManager manager)
    {
        base.Init(manager);
        manager.onDialogueFinished += SetTrue; // we subscribes to the dialogue's finish event to set this condition true.
    }
    
    public override void Dispose()
    {
        base.Dispose();
        manager.onDialogueFinished -= SetTrue; // we MUST also remember to unsubscribe to avoid leak over dialogues.
    }
}
```

### Initializing dialogues

Dialogues can appear visually in many different scenarios. This is why we created an `abstract` `DialogueManager` that you can extend wherever you need a dialogue to appear.

For example; if we want to show the dialogue in a UI we could create a dialogue manager like this:

```csharp
public class DialogueUI : DialogueManager // extend the dialogue manager
{
    public TextMeshProUGUI headerText, descriptionText;
    
    // this must exist in any class that extends DialogueManager
    //     it is called whenever the dialogue has finished.
    protected override void Hide()
    {
        headerText.text = ""; // clear the header
        descriptionText.text = ""; // clear the description
    }
    
    // this must exist in any class that extends DialogueManager
    //     it is called whenever a new dialogue is supposed to show
    protected override void Show(Dialogue dialogue)
    {
        headerText.text = dialogue.Header; // we set the header to the dialogue's header
        descriptionText.text = dialogue.Description; // we set the description to the dialogue's description
        
        StartCoroutine(DelayFinish()); // we delay the finish a bit to allow the player to see the dialogue before it finishes.
        // alt. we can use the Thread.Delay(this, Finish, 1) that comes with the package as a utility function.
    }
    
    private IEnumerator DelayFinish()
    {
        yield return new WaitForSeconds(5); // waits 5 seconds.
        Finish(); // this must always be called somewhere in a DialogueManager whenever the dialogue is supposed to be finished.
    }
}
```

For more examples, we can see the dialogue demo.

To later start a dialogue, we can simply call:

```csharp
public DialogueManager manager; // some reference to any manager (could be a UI)
public Dialogue dialogue; // some reference to the dialogue to show

manager.Run(dialogue); // run the new dialogue (could be placed in a Start() or any other desired place.
```
