3.6 KiB
Dialogue System
All authored text — NPC conversations, item pickup messages, battle narration — is written in .dialogue files and played back via DialogueManager (godot_dialogue_manager v3.10.4).
Plugin
- Autoload:
DialogueManager(registered inproject.godot) - Plugin must be enabled in Godot → Project Settings → Plugins → Dialogue Manager
.dialoguefiles are imported asDialogueResourceonce the plugin is active- Dialogue files live in
dialogue/organised by category (npc/,item/,battle/)
DialogueAction — the Cutscene bridge
cutscene/dialogue/DialogueAction.gd is the glue between the Cutscene queue and DialogueManager. It runs a .dialogue file through VNTextbox line-by-line and returns CUTSCENE_CONTINUE when the last line is dismissed.
# Add a dialogue step to any Cutscene
cutscene.addCallable(DialogueAction.getDialogueCallable(
load("res://dialogue/npc/test.dialogue"),
"start", # title to begin from
[entity] # extra_game_states: objects/dicts accessible in the .dialogue file
))
Movement is blocked automatically while dialogue runs because VNTextbox is open (EntityMovement._canMove() checks UI.TEXTBOX.isClosed).
Writing .dialogue files
~ title_name # entry point / jump target
Speaker: Line of dialogue.
Another line with no speaker.
~ another_section
Speaker: Variables resolve inline: {{some_property}}.
=> END # end this dialogue
Key syntax:
~ title— section anchor; use as thetitleargument toDialogueAction=> title— jump to another section;=> ENDends the dialogue{{variable}}— resolves a property from any autoload orextra_game_statesobjectdo AUTOLOAD.method()— call a method on any autoload (e.g.do PARTY.BACKPACK.addStack(stack))set AUTOLOAD.property = value— set a property- Option text— response branch (indented lines handle each branch)[if condition]— conditional line or response
Mutations fire automatically before the next dialogue line is returned — you do not handle them manually in GDScript.
Passing runtime data to dialogue
Use extra_game_states to expose GDScript objects to {{variable}} tokens:
class ItemDialogueState:
var item_name:String
var quantity:int
DialogueAction.getDialogueCallable(resource, 'start', [ItemDialogueState.new("Potato", 1)])
Then in the .dialogue file:
Obtained {{item_name}} x{{quantity}}.
NPC entities
Set these two exports on an Entity node whose interactType = CONVERSATION:
| Export | Purpose |
|---|---|
dialogueResource:DialogueResource |
The .dialogue file to run |
dialogueTitle:String |
Title (section) to start from (default "start") |
After first enabling the plugin and reimporting, assign dialogueResource directly in the Inspector. Until then, assign it in code (see TestMap.gd for the pattern).
Dialogue files
| File | Used by |
|---|---|
dialogue/npc/test.dialogue |
TestMap NPC (NotPlayer) |
dialogue/item/pickup.dialogue |
ItemAction — item pickup text with {{item_name}} and {{quantity}} |
dialogue/battle/narration.dialogue |
BattleCutsceneAction — move announcements, victory/defeat |
Response branching (current limitation)
DialogueAction auto-selects the first allowed response when a line has multiple options. There is no in-game response UI yet. To add one, replace the auto-select block in DialogueAction.dialogueCallable with a call to your response menu and await its selection signal.