AppleyAppley Docs
Docs/API Reference

Dialogue Systems

Create branching dialogue trees with choices and consequences.

29 min read Intermediate Updated 2026-07-01 v2.0 ~103 min to complete

Introduction

Dialogue systems power conversations with NPCs. This guide covers dialogue trees, branching choices, conditions, and consequences with data-driven design.

Guide 18 of 25

This is part of the Intermediate Guides collection. Category: Gameplay Systems. Estimated completion: 103 minutes. Difficulty: Intermediate.

Screenshot

Dialogue Systems
Dialogue Systems

Step-by-Step Guide

1

Design dialogue data

Create a data structure for dialogue: nodes with text, speaker, choices, conditions, and consequences.

2

Create a dialogue UI

Build a panel with speaker name, text (typewriter effect), and choice buttons at the bottom.

3

Implement branching

Each choice links to a different node. Some choices have conditions (requires item, quest flag).

4

Add typewriter effect

Reveal text character by character (30-50 chars/sec). Allow skipping to full text on click.

5

Handle consequences

Choices can give items, set quest flags, change reputation, or trigger events. Process on choice selection.

6

Save dialogue state

Track which dialogue nodes have been visited. Prevents repeating and unlocks new dialogue based on history.

FluxScript Example

Here is a complete FluxScript implementation for this guide:

Dialogue Systems — FluxScript
const DIALOGUE = {
  npc_blacksmith: {
    start: {
      speaker: "Borin the Blacksmith",
      text: "Ah, a traveler! My daughter was kidnapped by goblins. Will you help?",
      choices: [
        { text: "I will help.", next: "accept" },
        { text: "Not my problem.", next: "refuse" },
        { text: "What is the reward?", next: "reward" },
        { text: "[Persuade] Tell me more.", next: "persuade", condition: "persuasion > 5" }
      ]
    },
    accept: {
      speaker: "Borin",
      text: "Thank you! Take this sword.",
      action: { giveItem: "iron_sword", startQuest: "rescue_daughter" },
      next: "end"
    },
    refuse: {
      speaker: "Borin",
      text: "I see. If you change your mind, I will be here.",
      next: "end"
    },
    end: { end: true }
  }
}

currentNPC = null
currentNode = null
textIndex = 0

func startDialogue(npcId) {
  currentNPC = npcId
  currentNode = DIALOGUE[npcId].start
  gameRunning = false
  ui.show("dialoguePanel")
  showNode(currentNode)
}

func showNode(node) {
  if node.end { endDialogue(); return }
  if node.action applyAction(node.action)
  ui.setText("speakerName", node.speaker)
  textIndex = 0
  ui.setText("dialogueText", "")
  timer.start("typewriter", 0.03, node.text.length)
  ui.clearChoices()
  for i = 0 to (node.choices || []).length {
    choice = node.choices[i]
    if choice.condition == null || evalCondition(choice.condition) {
      ui.addChoice(choice.text, choice.next)
    }
  }
}

on timer("typewriter") {
  textIndex += 1
  ui.setText("dialogueText", string.substring(currentNode.text, 0, textIndex))
  if textIndex >= currentNode.text.length timer.stop("typewriter")
}

func endDialogue() {
  ui.hide("dialoguePanel")
  gameRunning = true
}

Node Graph Example

Prefer visual programming? Here is the equivalent Node Graph:

Dialogue Systems — Node Graph
[Function: startDialogue] --> [Set: currentNPC, node]
   --> [Pause: gameplay] --> [Show: dialoguePanel]
   --> [Show Node]

[Function: showNode] --> [Branch: end]
   +-- True --> [End Dialogue]
   +-- False --> [Apply: action]
              --> [Set: speaker name]
              --> [Start: typewriter timer]
              --> [Add: filtered choices]

[On Timer "typewriter"] --> [textIndex += 1]
   --> [Set Text: substring]
   --> [Branch: complete] --> [Stop]

Optimization Tips

Keep your implementation fast and efficient with these optimization tips:

  • Use data-driven dialogue. Store dialogue in JSON-like structures, not hardcoded in scripts. Lets writers edit without code.
  • Cache dialogue text. Loading and parsing dialogue data every conversation is wasteful. Load once and cache.
  • Use conditions for branching. Gate choices behind stats, items, or quest flags for meaningful player agency.
  • Pool dialogue UI elements. Reuse choice buttons instead of creating/destroying them per node. Prevents GC spikes.

Common Mistakes

Hardcoding dialogue in scripts

Use a data structure. Hardcoded dialogue is unmaintainable — writers cannot edit it.

No typewriter skip

Always allow clicking to skip the typewriter effect. Forced slow text frustrates fast readers.