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
- Go to
RPG Tools > Dialogue Tree Editor - The editor window will open with a visual interface
- You can either load an existing dialogue or create a new one
Step 2: Create Your First Dialogue
- Click "Create New" in the toolbar
- Choose a save location for your dialogue asset
- The editor will create a dialogue with one starting node
- Select the node to edit its properties
Step 3: Visual Node Editor
The visual editor provides a clear overview of dialogue flow:
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:
"Greetings, traveler!"
Auto β Node 1
"What brings you here?"
β’ "Just passing through" β Node 3
β’ "What is this place?" β Node 4
"I have a quest for you!"
Gives quest, ends dialogue
"Safe travels!"
Ends dialogue
"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
π― Clear Choices
Make player options clear and meaningful
π Character Voice
Each character should have a distinct speaking style
Guard: "Move along, nothing to see here."
β±οΈ Pacing
Vary dialogue length to maintain engagement