Dialogue System
Data-driven dialogue routing β not beginner typewriter tutorials.
NEVER Do in Dialogue Systems
- NEVER hardcode dialogue text in GDScript β Store lines in Resources / JSON / CSV so localization works.
- NEVER show choices the player has not unlocked β Hide (or intentionally gray) gated options.
- NEVER use unvalidated loose strings for node transitions β Typos in
next_node_idsoft-lock mid-convo; assert / registry IDs. - NEVER force a typewriter without skip β Click/confirm must finish the line immediately.
- NEVER drive reveal with per-character
Timer/OS.delay_msec()β Usevisible_ratio/visible_characters+ Tween (see typebox_effect.gd). - NEVER store dialogue cursor state only in the UI node β Scene changes drop the player; keep progress in the manager Autoload / session object.
- NEVER
get_node()from NPCs into Dialogue UI β Start via manager signals (start_dialogue(res)). - NEVER invent regex for BBCode β Prefer RichTextLabel BBCode / custom effects.
- NEVER save/load inside a dialogue node Resource β Nodes are data; persistence belongs to SaveSystem.
- NEVER hardcode portrait paths in code β Assign textures on node Resources or a portrait database.
Decision Tree: Authoring Engine
| Authoring need | Engine | MANDATORY scripts | Do NOT Load |
|---|---|---|---|
Designer-friendly .tres graphs in-repo |
Resource Autoload graph | dialogue_resource.gd β dialogue_manager_singleton.gd β dialogue_ui_controller.gd β typebox_effect.gd | dialogue_engine.gd JSON path |
| External writers / spreadsheet β JSON | JSON graph engine | dialogue_engine.gd (+ optional dialogue_manager.gd) β UI + typebox | Resource Autoload stack |
| Visual node editor in-project | GraphEdit authoring | Keep runtime on Resource or JSON export; GraphEdit is editor-only tooling | Shipping GraphEdit as the runtime walker |
| Conditions / quest gates | Either | branching_condition_validator.gd | Embedding flag checks in UI buttons |
| Portraits / expressions | Either | dialogue_portrait_manager.gd | β |
| Localization keys | Either | localized_dialogue_resource.gd | Hardcoded language if trees |
| Quest / gameplay hooks from lines | Either | dialogue_event_bridge.gd | Side effects inside UI controller |
Default golden path: Resource Autoload β UI controller β typebox_effect. Pick one runtime engine; do not run Resource manager and JSON engine in parallel.
Available Scripts (single catalog)
Runtime (golden path)
- dialogue_resource.gd β conversation tree Resource
- dialogue_node_data.gd β single line / speaker / portrait metadata
- dialogue_option_data.gd β choice + conditions
- dialogue_manager_singleton.gd β MANDATORY Autoload walker + signals
- dialogue_ui_controller.gd β MANDATORY labels / choice buttons
- typebox_effect.gd β MANDATORY skip-safe Tween
visible_ratioreveal
Supporting
- dialogue_event_bridge.gd β fire gameplay events from nodes
- branching_condition_validator.gd β flag/stat gates
- localized_dialogue_resource.gd β translation keys
- dialogue_portrait_manager.gd β expression swaps
Alternate engines (load only if decision tree says so)
- dialogue_engine.gd β JSON graphs + BBCode
[trigger:]tags - dialogue_manager.gd β alternate data-driven walker
- dialogue_graph_editor.gd β
@toolGraphEdit auditor (editor-only) - dialogue_lipsync.gd β TTS boundary lipsync helper
- dialogue_stat_logger.gd β choice analytics Logger
Typewriter Contract (skip-safe)
Use typebox_effect.gd: set full text, tween visible_ratio (or RichTextLabel visible_characters) from 0β1. On skip input: kill tween and snap visibility to complete. Do not spawn a Timer per character.
Elite Deltas
- GraphEdit auditor: dialogue_graph_editor.gd (
@tool) β export to Resource/JSON for runtime. - Audio-driven lines: dialogue_lipsync.gd β TTS boundaries; still allow skip.
- Analytics: dialogue_stat_logger.gd β
[CHOICE]log prefix; no PII.
MANDATORY for GraphEdit tooling, TTS/lipsync, analytics, and moved inline manager/UI tutorials: elite-dialogue-patterns.md. Do NOT Load for Resource Autoload golden path only.
Reference
Progressive disclosure: open Official Documentation links only when researching a specific API; load Related Skills when routing to a peer domain β do not preload the whole lattice.
Official Documentation
- Resources β Why dialogue graphs belong in
Resource/.tresdata instead of hardcoded strings in scripts. - BBCode in RichTextLabel β Native markup for speaker emphasis, custom tags, and effects without rolling your own parser.
- RichTextLabel β
visible_characters/ image helpers and BBCode APIs the dialogue UI should drive for typewriter and portraits. - Internationalizing games β
tr()/ TranslationServer workflow so line text stays key-based across locales. - Localization using spreadsheets β CSV translation tables that map cleanly onto dialogue
text_keyfields. - Importing translations β How Godot imports CSV/PO so localized dialogue resources resolve at runtime.
- Using signals β Emit line/choice/end events upward so UI, quests, and audio never hard-reference the manager internals.
- Singletons (Autoload) β Register a
DialogueManagerthat survives scene changes and owns traversal state. - Tween β Drive
visible_ratio/ character reveal timing without blocking the main thread. - Text-to-speech β
DisplayServerTTS callbacks for placeholder VO and lipsync-adjacent timing. - GraphEdit β Editor surface for authoring branching dialogue graphs when
.treslists become unwieldy. - JSON β Parse external dialogue graph files when designers prefer JSON over Resources.
Related Skills
Prerequisites
- godot-project-foundations β Autoload registration, input for advance/skip, and project layout dialogue UI scenes plug into.
- godot-gdscript-mastery β Typed Resources, signals,
await, and Callables required before branching engines and UI bridges. - godot-resource-data-patterns β Canonical patterns for
DialogueLine/ graph Resources, exports, and avoiding duplicated mutable state. - godot-autoload-architecture β Singleton ownership and boot order for a global
DialogueManagerthat must outlive scene swaps.
Complements
- godot-signal-architecture β Signal-up / call-down contracts for
line_displayed, choice selection, and narrative event bridges. - godot-ui-rich-text β RichTextLabel BBCode, custom effects, and image embedding beyond the basics used in typewriter UIs.
- godot-ui-containers β Layout choice buttons and dialogue panels without fighting Control sizing and focus.
- godot-tweening β Skip-safe Tweens for character reveal, portrait entry, and panel transitions.
- godot-audio-systems β Voice-line players, bus ducking during dialogue, and subtitle sync with spoken audio.
- godot-quest-system β Quest flags and objectives that gate conditional choices and fire from dialogue event bridges.
- godot-save-load-systems β Persist dialogue flags / seen-node state outside UI nodes so progress survives reloads.
Downstream / consumers
- godot-genre-visual-novel β Full VN presentation loops consume this skillβs graph traversal, portraits, and choice UI patterns.
- godot-inventory-system β Dialogue effects often grant/require items; keep grant logic in inventory, not inside line Resources.
- godot-monte-carlo-balancer β Simulate skill-check / branching choice trees when narrative gates or reward paths need balance passes.
Master
- godot-master β Library router and mirrored module entry; open when discovering which Domain Skill owns narrative, UI, or quest concerns.