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

# Dialogue Generation

Generating dialogue graphs at runtime.

Creating dialogue through code is straightforward once you understand the core methods. This tutorial walks you through building a dialogue graph step by step, showing how each piece of code corresponds to its representation in the dialogue graph editor.

## 1. Create a New Dialogue Graph

Just use the `DialogueBuilder.New` method to create a new instance of a `DialogueGraph`.

```csharp
DialogueGraph myDialogueGraph = DialogueBuilder.New<DialogueGraph>();
```

You can use this method to create new dialogue groups, characters, and emotions as well.

At this point, we simply have an empty graph.

<figure><img src="https://1123894923-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fi5EhvGPJLvE6Kc1rE7X5%2Fuploads%2FVLHd7cTIfLy4nRSTosHo%2Fimage.png?alt=media&amp;token=d7e4c3e0-f521-445d-8873-6a8b79be8e7e" alt="" width="563"><figcaption></figcaption></figure>

## 2. Add a Node

Use the `Add` method to add any node to the graph.

```csharp
Node myNode = myDialogueGraph.Add<Node>();
```

Replace `Node` with one of the types below:

* `DialogueNode`
* `ChoiceNode`
* `DelayNode`
* `SoundNode`
* `ActionNode`
* `BooleanNode`
* `NestNode`

To start, we'll add a dialogue node:

```csharp
DialogueNode myDialogueNode = myDialogueGraph.Add<DialogueNode>();
```

<figure><img src="https://1123894923-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fi5EhvGPJLvE6Kc1rE7X5%2Fuploads%2FKd54lg4iO8q1t8HixAk5%2Fimage.png?alt=media&amp;token=8c953767-0c5d-4d1d-8a8b-4a46f25e84b2" alt="" width="563"><figcaption></figcaption></figure>

The first node added is the starting node, however, you can change it by calling `SetAsStartingNode` on another node.

```csharp
myNode.SetAsStartingNode();
```

## 3. Set the Properties

After adding a node, set it's properties using the available methods.

#### Dialogue Node

You can set the dialogue, the character saying the dialogue, and the emotion with the `SetDialogue` method.

```csharp
myDialogueNode.SetDialogue("My dialogue.", "My Character Name", "My Emotion Name");
```

Localization is supported:

<pre class="language-csharp"><code class="lang-csharp"><strong>myDialogueNode.SetDialogue(new List&#x3C;Localization.LocaleString>()
</strong>{
    new("en", "Hello, world!"),
    new("es", "¡Hola, mundo!"),
    new("fr", "Bonjour le monde!"),
}, "My Character Name");
</code></pre>

#### Choice Node

The `AddChoices` method allows you to add any number of choices. Simply pass a pair of strings (choice name, and the display text) that represent the choices.

```csharp
myChoiceNode.AddChoices(("Choice 1", "Yes"), ("Choice 2", "No"))
```

#### Delay Node

Use `SetDelay` and pass a float that represents the number of seconds to delay the dialogue. 1f = 1s.

```csharp
myDelayNode.SetDelay(1f)
```

#### Sound Node

The `SetSound` method sets the sound that will be played. It requires a reference to an `AudioClip`.

```csharp
mySoundNode.SetSound(myAudioClip)
```

#### Action Node

You can set an action to execute with the `SetAction` method.

```csharp
myActionNode.SetAction(() => Debug.Log("It worked!"));
```

#### Boolean Node

The `SetCondition` method allows you to pass custom branching logic. The method must return `bool`.

```csharp
bool isFeelSpeakCool = true;
myBooleanNode.SetCondition(() =>
{
    return isFeelSpeakCool;
});
```

#### Nest Node

To set nested dialogue, pass either a `DialogueGraph` or `DialogueGroup` in the `SetNestedDialogue` method.

```csharp
myNestNode.SetNestedDialogue(dialogueGraphToNest);
```

### Visual Representation

For this example, we'll make a demo character, Pinky, say "Hello, world!".

```csharp
myDialogueNode.SetDialogue("Hello, world!", "Pinky");
```

<figure><img src="https://1123894923-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fi5EhvGPJLvE6Kc1rE7X5%2Fuploads%2FGtSBKlCwI9nyR1QPveCM%2Fimage.png?alt=media&amp;token=f550f2ba-f2e5-4d96-89b6-b2a32bd9e267" alt="" width="563"><figcaption></figcaption></figure>

## 4. Subsequent Additions

The **next** node you add will **automatically** connect to the previous node.

For this example, we'll add a choice node and add 2 choices.

```csharp
ChoiceNode myChoiceNode = myDialogueGraph.Add<ChoiceNode>();
myChoiceNode.AddChoices(("Choice 1", "Hello!"), ("Choice 2", "Hi!"))
```

<figure><img src="https://1123894923-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fi5EhvGPJLvE6Kc1rE7X5%2Fuploads%2F6lwUElJG4GGCredNP33f%2Fimage_2026-07-19_213740527.png?alt=media&amp;token=9382deeb-f9e3-4bd2-9347-352021f29b8d" alt=""><figcaption></figcaption></figure>

## 5. Branching

Choice and Boolean nodes both have multiple output ports, but automatic connections only use the first output port. This is where the `Branch` method comes into play.

The `Branch` method creates a `Brancher` that you can use to use a specific output port of a node for the next added node.

```csharp
myDialogueGraph.Branch(out Brancher brancher) // Create brancher
    .From(brancher.branches[0]) // Start branching from first choice (or first output port of the choice node)
    .Add<DialogueNode>().SetDialogue("You selected option 1!", "Pinky") // Add dialogue for option 1
    .From(brancher.branches[1]) // Start branching from second choice
    .Add<DialogueNode>().SetDialogue("You selected option 2!", "Pinky") // Add dialogue for option 2
```

<figure><img src="https://1123894923-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fi5EhvGPJLvE6Kc1rE7X5%2Fuploads%2FIqJOGvX34erFfn3rRMQW%2Fimage.png?alt=media&amp;token=1cd9cc1b-b5f1-42a9-9d3f-49ea8089348b" alt=""><figcaption></figcaption></figure>

Alternatively, you can use the `ConnectWith` method to connect with a specified node.

```csharp
myFirstNode.ConnectWith(mySecondNode, 1); // Second parameter is the output port index
```

## 6. Final Notes

The above is all you really need to know to generate dialogue graphs at runtime.

For the other node settings you can set from the node itself. For example:

```csharp
myDialogueNode.automaticNextOnComplete = true;
```

The `ChoiceNode` has a method to help set the timeout:

```csharp
myChoiceNode.SetTimeout(true, 10f); // Choice times out after 10s
```

## Example Script

The script below is used for the scripting demo. It requires the demo characters to be available as it generates dialogue with them.

```csharp
/// <summary>
/// Generates dialogue for the scripting demo scene.
/// </summary>
public class DialogueScriptingDemo : MonoBehaviour
{
    public AudioClip audioClip;
    public GameObject structures;

    /// <summary>
    /// Generates dialogue with Pinky.
    /// </summary>
    public void GenerateDialogueWithPinky()
    {
        // Create a new dialogue graph
        var graph = DialogueBuilder.New<DialogueGraph>();
        
        // Create dialogue sequence
        graph.Add<DialogueNode>().SetDialogue("Hi, this dialogue was generated at runtime!", "Pinky")
            .Add<DialogueNode>().SetDialogue("Now let's test choices! Are you ready?", "Pinky")
            .Add<ChoiceNode>().AddChoices(("Choice 1", "Yes"), ("Choice 2", "No"))
            .Branch(out Brancher branch1)
            .From(branch1.branches[0])
            .Add<DialogueNode>().SetDialogue("You chose yes! Is that correct?", "Pinky")
            .Add<ChoiceNode>().AddChoices(("Choice 1", "Yes"), ("Choice 2", "No"))
            .Branch(out Brancher branch2)
            .From(branch2.branches[0])
            .Add<DialogueNode>().SetDialogue("I'm glad everything is working as intended!", "Pinky")
            .From(branch2.branches[1])
            .Add<DialogueNode>().SetDialogue("Hmm... I guess something isn't working as intended.", "Pinky")
            .From(branch1.branches[1])
            .Add<DialogueNode>().SetDialogue("You chose no!", "Pinky")
            .Merge<DialogueNode>(branch1.branches[1], branch2.branches[0], branch2.branches[1]).SetDialogue("All pathways lead here due to branch merging! Isn't that great?", "Pinky", "Happy")
            .Add<DialogueNode>().SetDialogue("Yeah, that's pretty cool.", "Robo");

        // Start the dialogue (this uses the first dialogue box in the scene)
        DialogueBox.First.StartDialogue(graph);
    }

    /// <summary>
    /// Generates dialogue with Goldy.
    /// </summary>
    public void GenerateDialogueWithGoldy()
    {
        // Create a new dialogue graph
        var graph = DialogueBuilder.New<DialogueGraph>();

        // Create dialogue sequence
        graph.Add<DialogueNode>().SetDialogue("Alright, let's test some nodes.", "Goldy")
            .Add<ChoiceNode>().AddChoices(
            ("Sound", "Sound Node"),
            ("Delay", "Delay Node"),
            ("Action", "Action Node"),
            ("Boolean", "Boolean Node"),
            ("Nest", "Nest Node"),
            ("Exit", "Exit"))
            .Branch(out Brancher brancher)
            .From(brancher.branches[0])
            .Add<DialogueNode>().SetDialogue("Alright, let's play a sound.", "Goldy")
            .Add<SoundNode>().SetSound(audioClip)
            .Add<DialogueNode>().SetDialogue("Did you hear that?", "Goldy")
            .ConnectWith(graph.choiceNodes[0])
            .From(brancher.branches[1])
            .Add<DialogueNode>().SetDialogue("Alright, let's delay the dialogue for 2 seconds.", "Goldy")
            .Add<DelayNode>().SetDelay(2f)
            .Add<DialogueNode>().SetDialogue("And we're back!", "Goldy")
            .ConnectWith(graph.choiceNodes[0])
            .From(brancher.branches[2])
            .Add<DialogueNode>().SetDialogue("Alright, how about we toggle the structures?", "Goldy")
            .Add<ActionNode>().SetAction(() => structures.SetActive(!structures.activeSelf))
            .Add<DialogueNode>().SetDialogue("Neat, huh?", "Goldy")
            .ConnectWith(graph.choiceNodes[0])
            .From(brancher.branches[3])
            .Add<DialogueNode>().SetDialogue("Alright, a random number will be generated, 0 or 1. Based on the random number, the next dialogue will either be from me or Pinky.", "Goldy")
            .Add<BooleanNode>().SetCondition(() =>
            {
                var random = Random.Range(0, 2);
                return random == 0;
            })
            .Branch(out Brancher booleanBranch)
            .From(booleanBranch.branches[0])
            .Add<DialogueNode>().SetDialogue("The number was 0!", "Goldy")
            .ConnectWith(graph.choiceNodes[0])
            .From(booleanBranch.branches[1])
            .Add<DialogueNode>().SetDialogue("The number was 1!", "Pinky")
            .ConnectWith(graph.choiceNodes[0])
            .From(brancher.branches[4])
            .Add<DialogueNode>().SetDialogue("Alright, how about we nest this dialogue within itself? Make sure to exit!", "Goldy")
            .Add<NestNode>().SetNestedDialogue(graph)
            .Add<DialogueNode>().SetDialogue("Welcome back!", "Goldy")
            .Add<DialogueNode>().SetDialogue("...", "Robo")
            .Add<DialogueNode>().SetDialogue("What?", "Goldy")
            .ConnectWith(graph.choiceNodes[0])
            .From(brancher.branches[5])
            .Add<DialogueNode>().SetDialogue("See ya!", "Goldy");

        // Start the dialogue (this uses the first dialogue box in the scene)
        DialogueBox.First.StartDialogue(graph);
    }

    /// <summary>
    /// Generates some localized dialogue.
    /// </summary>
    public void GenerateDialogueLocalized()
    {
        // Create a new dialogue graph
        var graph = DialogueBuilder.New<DialogueGraph>();

        // Create localized dialogue sequence
        graph.Add<DialogueNode>().SetDialogue(new List<Localization.LocaleString>()
        {
            new("en", "Hello, world!"), // English
            new("es", "¡Hola, mundo!"), // Spanish
            new("fr", "Bonjour le monde!"), // French
        }, "Pinky");

        // Start the dialogue (this uses the first dialogue box in the scene)
        DialogueBox.First.StartDialogue(graph);
    }
}
```
