Creating Dialogue Trees

Master the dialogue system to create engaging conversations and interactive storytelling.

Dialogue System Overview

The dialogue system supports complex branching conversations with conditions, actions, and dynamic content.

🌳 Branching Conversations

Create complex dialogue trees with multiple paths and outcomes

🎭 Character Portraits

Display character images and names for immersive conversations

⚑ Conditional Logic

Show different options based on quests, items, or player stats

πŸŽͺ Action Triggers

Start quests, give items, or trigger events through dialogue

Using the Dialogue Tree Editor

Step 1: Open the Editor

  1. Go to RPG Tools > Dialogue Tree Editor
  2. The editor window will open with a visual interface
  3. You can either load an existing dialogue or create a new one
Dialogue Tree Editor

Step 2: Create Your First Dialogue

  1. Click "Create New" in the toolbar
  2. Choose a save location for your dialogue asset
  3. The editor will create a dialogue with one starting node
  4. Select the node to edit its properties

Step 3: Visual Node Editor

The visual editor provides a clear overview of dialogue flow:

Green Node: Starting dialogue node
Blue Lines: Automatic transitions
Orange Lines: Player choice transitions
Red Node: End dialogue node

Dialogue Node Types

Basic Dialogue Node

The foundation of all conversations:

[System.Serializable]
public class DialogueNode
{
    [Header("Character")]
    public string characterName = "NPC";
    public Sprite characterPortrait;
    
    [Header("Dialogue")]
    [TextArea(3, 6)]
    public string dialogueText = "Hello there!";
    
    [Header("Flow Control")]
    public int nextNodeIndex = -1;      // -1 means end dialogue
    public DialogueChoice[] choices;     // Player response options
    
    [Header("Effects")]
    public DialogueAction[] actions;     // Actions to perform
    public AudioClip voiceClip;         // Optional voice acting
}

Choice Nodes

Nodes that present options to the player:

[System.Serializable]
public class DialogueChoice
{
    [Header("Choice Text")]
    public string choiceText = "Yes";
    public int nextNodeIndex = -1;
    
    [Header("Availability")]
    public DialogueCondition condition;  // When this choice is available
    
    [Header("Effects")]
    public DialogueAction action;        // What happens when chosen
    
    [Header("UI")]
    public bool isEnabled = true;
    public Color textColor = Color.white;
}

// Example choices:
// "I'll help you!" -> leads to quest acceptance
// "Not right now." -> ends dialogue
// "Tell me more." -> leads to exposition node

Creating Dialogue Flow

Plan your dialogue structure:

Node 0 (Start)
"Greetings, traveler!"
Auto β†’ Node 1
↓
Node 1 (Choices)
"What brings you here?"
β€’ "I'm looking for work" β†’ Node 2
β€’ "Just passing through" β†’ Node 3
β€’ "What is this place?" β†’ Node 4
Node 2
"I have a quest for you!"
Gives quest, ends dialogue
Node 3
"Safe travels!"
Ends dialogue
Node 4
"This is Riverside Village..."
Back to Node 1

Dialogue Conditions

Available Condition Types

Control when dialogue options appear:

πŸ† Quest Status

Check if a quest is active, completed, or not started

Quest "Village_Help" is Active

πŸŽ’ Has Item

Verify the player has specific items

Player has "Ancient Key" x1

πŸ“Š Player Level

Require minimum player level

Player Level >= 10

πŸ’° Gold Amount

Check if player has enough gold

Player Gold >= 100

πŸ”’ Custom Variable

Use custom flags and variables

GameFlag "met_king" = true

⏰ Time-Based

Show options based on game time

Time of day is "Night"

Implementing Custom Conditions

Create your own condition types:

[System.Serializable]
public class DialogueCondition
{
    public ConditionType type;
    
    [Header("Quest Conditions")]
    public string questId;
    public QuestStatus requiredStatus;
    
    [Header("Item Conditions")]
    public Item requiredItem;
    public int requiredQuantity = 1;
    
    [Header("Stat Conditions")]
    public StatType statType;
    public int requiredValue;
    
    [Header("Custom Conditions")]
    public string customFlag;
    public bool customValue;
    
    public bool IsConditionMet(PlayerStats player)
    {
        switch (type)
        {
            case ConditionType.QuestActive:
                return QuestManager.Instance.IsQuestActive(questId);
                
            case ConditionType.QuestCompleted:
                return QuestManager.Instance.IsQuestCompleted(questId);
                
            case ConditionType.HasItem:
                var inventory = player.GetComponent();
                return inventory.HasItem(requiredItem, requiredQuantity);
                
            case ConditionType.PlayerLevel:
                return player.level >= requiredValue;
                
            case ConditionType.CustomFlag:
                return GameManager.Instance.GetCustomFlag(customFlag) == customValue;
                
            default:
                return true;
        }
    }
}

Complex Condition Logic

Combine multiple conditions:

// Advanced condition checking
public class ComplexCondition
{
    public DialogueCondition[] requiredConditions;  // ALL must be true (AND logic)
    public DialogueCondition[] optionalConditions;  // ANY can be true (OR logic)
    
    public bool IsConditionMet(PlayerStats player)
    {
        // Check required conditions (AND logic)
        foreach (var condition in requiredConditions)
        {
            if (!condition.IsConditionMet(player))
            {
                return false; // Fail if any required condition fails
            }
        }
        
        // Check optional conditions (OR logic)
        if (optionalConditions.Length > 0)
        {
            foreach (var condition in optionalConditions)
            {
                if (condition.IsConditionMet(player))
                {
                    return true; // Pass if any optional condition passes
                }
            }
            return false; // Fail if no optional conditions pass
        }
        
        return true; // Pass if all required conditions met
    }
}

// Example usage:
// Required: Player Level >= 5 AND Has "Magic License"
// Optional: Quest "Mage Guild" is Active OR Has "Recommendation Letter"

Dialogue Actions

Action Types

Actions that can be triggered by dialogue:

🎯 Start Quest

Begin a new quest for the player

StartQuest("village_defense")

🎁 Give Item

Add items to player inventory

GiveItem("Health Potion", 3)

⭐ Give Experience

Award experience points

GiveExperience(150)

πŸ’° Give Gold

Add gold to player's wallet

GiveGold(50)

🚩 Set Flag

Set custom game flags

SetFlag("met_wizard", true)

🎡 Play Sound

Trigger audio effects

PlaySound("quest_complete")

Implementing Actions

Create the action system:

[System.Serializable]
public class DialogueAction
{
    public ActionType type;
    
    [Header("Quest Actions")]
    public string questId;
    
    [Header("Item Actions")]
    public Item item;
    public int quantity = 1;
    
    [Header("Value Actions")]
    public int intValue;
    public string stringValue;
    public bool boolValue;
    
    [Header("Audio Actions")]
    public AudioClip audioClip;
    
    public void Execute()
    {
        var player = GameManager.Instance.playerStats;
        var inventory = player.GetComponent();
        
        switch (type)
        {
            case ActionType.StartQuest:
                QuestManager.Instance.StartQuest(questId);
                break;
                
            case ActionType.CompleteQuest:
                QuestManager.Instance.CompleteQuest(questId);
                break;
                
            case ActionType.GiveItem:
                inventory.AddItem(item, quantity);
                ShowItemNotification(item, quantity);
                break;
                
            case ActionType.RemoveItem:
                inventory.RemoveItem(item, quantity);
                break;
                
            case ActionType.GiveExperience:
                player.GainExperience(intValue);
                ShowExperienceNotification(intValue);
                break;
                
            case ActionType.GiveGold:
                inventory.AddGold(intValue);
                ShowGoldNotification(intValue);
                break;
                
            case ActionType.SetFlag:
                GameManager.Instance.SetCustomFlag(stringValue, boolValue);
                break;
                
            case ActionType.PlaySound:
                if (audioClip != null)
                    AudioManager.Instance.PlaySFX(audioClip);
                break;
                
            case ActionType.ChangeScene:
                GameManager.Instance.LoadScene(stringValue);
                break;
        }
    }
    
    private void ShowItemNotification(Item item, int quantity)
    {
        string message = quantity > 1 ? 
            $"Received {item.itemName} x{quantity}" : 
            $"Received {item.itemName}";
            
        UIManager.Instance.ShowNotification(message);
    }
}

Chain Actions

Execute multiple actions in sequence:

// Example: Complete quest and give rewards
public void ExecuteQuestCompletion()
{
    var actions = new DialogueAction[]
    {
        new DialogueAction { type = ActionType.CompleteQuest, questId = "fetch_herbs" },
        new DialogueAction { type = ActionType.GiveExperience, intValue = 200 },
        new DialogueAction { type = ActionType.GiveGold, intValue = 100 },
        new DialogueAction { type = ActionType.GiveItem, item = magicSword, quantity = 1 },
        new DialogueAction { type = ActionType.SetFlag, stringValue = "hero_status", boolValue = true }
    };
    
    foreach (var action in actions)
    {
        action.Execute();
    }
}

Advanced Dialogue Features

Dynamic Text Replacement

Use variables in dialogue text:

// Dynamic dialogue text with placeholders
public string ProcessDialogueText(string rawText, PlayerStats player)
{
    string processedText = rawText;
    
    // Replace player name
    processedText = processedText.Replace("{PLAYER_NAME}", player.playerName);
    
    // Replace player level
    processedText = processedText.Replace("{PLAYER_LEVEL}", player.level.ToString());
    
    // Replace current quest progress
    processedText = processedText.Replace("{QUEST_PROGRESS}", 
        QuestManager.Instance.GetQuestProgress("current_quest").ToString());
    
    // Replace item quantities
    var inventory = player.GetComponent();
    processedText = processedText.Replace("{GOLD_AMOUNT}", 
        inventory.GetGoldAmount().ToString());
    
    return processedText;
}

// Example dialogue text:
// "Greetings, {PLAYER_NAME}! I see you're level {PLAYER_LEVEL}. 
//  You currently have {GOLD_AMOUNT} gold pieces."
// 
// Becomes:
// "Greetings, Hero! I see you're level 12. 
//  You currently have 350 gold pieces."

Dialogue State Management

Track conversation history and state:

public class DialogueState : MonoBehaviour
{
    [System.Serializable]
    public class NPCDialogueState
    {
        public string npcId;
        public int lastNodeIndex = 0;
        public bool hasMetBefore = false;
        public Dictionary customValues = new Dictionary();
    }
    
    private Dictionary npcStates = 
        new Dictionary();
    
    public NPCDialogueState GetNPCState(string npcId)
    {
        if (!npcStates.ContainsKey(npcId))
        {
            npcStates[npcId] = new NPCDialogueState { npcId = npcId };
        }
        return npcStates[npcId];
    }
    
    public void SetNPCMet(string npcId)
    {
        var state = GetNPCState(npcId);
        state.hasMetBefore = true;
    }
    
    public bool HasMetNPC(string npcId)
    {
        return GetNPCState(npcId).hasMetBefore;
    }
}

// Usage in dialogue conditions:
// Show "Nice to see you again!" if player has met this NPC before
// Show "I don't think we've met..." for first-time meetings

Dialogue Events and Callbacks

Hook into dialogue system events:

public class DialogueManager : MonoBehaviour
{
    // Events for other systems to subscribe to
    public static event System.Action OnDialogueNodeEntered;
    public static event System.Action OnDialogueChoiceSelected;
    public static event System.Action OnDialogueStarted;
    public static event System.Action OnDialogueEnded;
    
    public void StartDialogue(DialogueTree dialogue, NPC speaker)
    {
        // Notify other systems
        OnDialogueStarted?.Invoke(dialogue);
        
        // Pause game
        GameManager.Instance.ChangeGameState(GameState.Dialogue);
        
        // Show UI
        dialogueUI.ShowDialogue(dialogue, speaker);
    }
    
    public void SelectChoice(DialogueChoice choice)
    {
        // Notify systems about choice
        OnDialogueChoiceSelected?.Invoke(choice);
        
        // Execute choice action
        if (choice.action != null)
        {
            choice.action.Execute();
        }
        
        // Continue to next node
        if (choice.nextNodeIndex >= 0)
        {
            ShowNode(choice.nextNodeIndex);
        }
        else
        {
            EndDialogue();
        }
    }
}

// Example subscriber:
public class QuestTracker : MonoBehaviour
{
    void OnEnable()
    {
        DialogueManager.OnDialogueChoiceSelected += OnChoiceSelected;
    }
    
    void OnChoiceSelected(DialogueChoice choice)
    {
        // Track dialogue choices for quest objectives
        if (choice.choiceText.Contains("accept"))
        {
            // Player accepted something - might be quest related
            CheckQuestObjectives(choice);
        }
    }
}

Localization Support

Prepare dialogues for multiple languages:

[System.Serializable]
public class LocalizedDialogueNode
{
    [Header("Localization")]
    public string localizationKey;
    
    [Header("Fallback Text")]
    public string fallbackText;
    
    public string GetLocalizedText()
    {
        if (!string.IsNullOrEmpty(localizationKey))
        {
            string localizedText = LocalizationManager.Instance.GetText(localizationKey);
            if (!string.IsNullOrEmpty(localizedText))
            {
                return localizedText;
            }
        }
        
        return fallbackText;
    }
}

// Localization files (JSON example):
// en.json
{
    "npc.elder.greeting": "Welcome to our village, traveler!",
    "npc.elder.quest_offer": "I have a task that requires your skills.",
    "choice.accept_quest": "I'll help you.",
    "choice.decline_quest": "Not interested."
}

// es.json  
{
    "npc.elder.greeting": "Β‘Bienvenido a nuestro pueblo, viajero!",
    "npc.elder.quest_offer": "Tengo una tarea que requiere tus habilidades.",
    "choice.accept_quest": "Te ayudarΓ©.",
    "choice.decline_quest": "No me interesa."
}

Dialogue Writing Best Practices

πŸ“ Natural Speech

Write dialogue that sounds like how people actually speak

βœ… "Hey, you look like you could use some help."
❌ "Greetings, adventurer. I observe that you require assistance."

🎯 Clear Choices

Make player options clear and meaningful

βœ… "I'll help you find your missing daughter."
❌ "Option A"

🌟 Character Voice

Each character should have a distinct speaking style

βœ… Scholar: "The theoretical implications are fascinating..."
Guard: "Move along, nothing to see here."

⏱️ Pacing

Vary dialogue length to maintain engagement

βœ… Mix short responses with longer exposition
❌ Every line is exactly the same length

Continue Learning

Explore related tutorials to expand your knowledge