Skip to main content

Overview

Once you’ve written your dialogue, you’ll need to integrate it into your game. Dialogue Manager provides the DialogueManager singleton and DialogueLine class to request and display dialogue lines programmatically.

Getting Dialogue Lines

Basic Usage

The simplest way to get a line of dialogue is by calling get_next_dialogue_line():
var resource = load("res://dialogue/conversation.dialogue")
var dialogue_line = await DialogueManager.get_next_dialogue_line(resource, "start")
You can also call get_next_dialogue_line() directly on the resource:
var resource = load("res://dialogue/conversation.dialogue")
var dialogue_line = await resource.get_next_dialogue_line("start")
The get_next_dialogue_line() method traverses each line, running mutations along the way, and returns the first printable line of dialogue.

Example Dialogue Flow

Given this dialogue file:
~ start

Nathan: Hi! I'm Nathan.
Nathan: Here are some options.
- First one
	Nathan: You picked the first one.
- Second one
	Nathan: You picked the second one.
The first call to get_next_dialogue_line(resource, "start") would return a DialogueLine containing Nathan: Hi! I'm Nathan.

Getting the Next Line

To continue the dialogue, use the next_id property from the current line:
# Get the first line
var dialogue_line = await DialogueManager.get_next_dialogue_line(resource, "start")

# Get the next line
dialogue_line = await DialogueManager.get_next_dialogue_line(resource, dialogue_line.next_id)
When a line contains response options, each option has its own next_id property to continue along that branch:
if dialogue_line.responses.size() > 0:
	# Show response options to the player
	for response in dialogue_line.responses:
		print(response.text)
	
	# After player selects a response:
	var selected_response = dialogue_line.responses[0]
	dialogue_line = await resource.get_next_dialogue_line(selected_response.next_id)

DialogueLine Structure

The DialogueLine class contains all information about a line of dialogue:
id
String
The unique ID of this line
type
String
The internal type: TYPE_DIALOGUE or TYPE_MUTATION
next_id
String
The ID of the next line to display
character
String
The name of the character speaking this line
text
String
The dialogue text to display
translation_key
String
The key used for translating this line
responses
Array
List of response options attached to this line
tags
PackedStringArray
Any #tags included in the line
time
String
Auto-advance timing: a float (seconds), "auto", or empty string
speeds
Dictionary
A map of speed changes for typing out the dialogue
inline_mutations
Array[Array]
Mutations to run while typing out the text

Working with Tags

Use the helper methods to check for and retrieve tag values:
# Check if a line has a tag
if dialogue_line.has_tag("voice"):
	var voice_file = dialogue_line.get_tag_value("voice")
	audio_player.stream = load(voice_file)
	audio_player.play()

Game Integration Patterns

Basic Integration

1

Load the dialogue resource

@onready var dialogue_resource = preload("res://dialogue/npc_conversation.dialogue")
2

Request the first line

func start_dialogue():
	var line = await DialogueManager.get_next_dialogue_line(dialogue_resource, "greeting")
	show_dialogue(line)
3

Handle dialogue display and advancement

func show_dialogue(line: DialogueLine):
	if line == null:
		# Dialogue ended
		end_dialogue()
		return
	
	# Display character name and text
	character_label.text = line.character
	dialogue_label.text = line.text
	
	# Check for responses
	if line.responses.size() > 0:
		show_response_options(line.responses)
	else:
		# Wait for player input to continue
		await advance_button.pressed
		var next_line = await dialogue_resource.get_next_dialogue_line(line.next_id)
		show_dialogue(next_line)

Advanced Integration with Extra Game States

Pass game state objects to make them available in dialogue conditions:
var player = get_node("/root/Player")
var inventory = get_node("/root/Inventory")

var line = await DialogueManager.get_next_dialogue_line(
	dialogue_resource,
	"start",
	[player, inventory]
)
In your dialogue, you can now reference these objects:
~ start

if player.level >= 5
	Nathan: You're quite experienced!
else
	Nathan: You're still learning.

if inventory.has_item("key")
	Nathan: I see you found the key!

Handling Response Selection

When a line contains response options, present them to the player:
func show_response_options(responses: Array):
	# Clear previous options
	for child in response_container.get_children():
		child.queue_free()
	
	# Create buttons for each response
	for response in responses:
		var button = Button.new()
		button.text = response.text
		button.pressed.connect(func(): on_response_selected(response))
		response_container.add_child(button)

func on_response_selected(response: DialogueResponse):
	var next_line = await dialogue_resource.get_next_dialogue_line(response.next_id)
	show_dialogue(next_line)

Auto-advancing Dialogue

Handle lines with automatic timing:
func show_dialogue(line: DialogueLine):
	if line == null:
		return
	
	display_text(line)
	
	if line.time != "":
		# Calculate wait time
		var wait_time: float
		if line.time == "auto":
			wait_time = line.text.length() * 0.02  # 0.02 seconds per character
		else:
			wait_time = line.time.to_float()
		
		# Wait and advance automatically
		await get_tree().create_timer(wait_time).timeout
		var next_line = await dialogue_resource.get_next_dialogue_line(line.next_id)
		show_dialogue(next_line)

Using Custom Current Scene

If your game has a custom scene management system, override the get_current_scene callable:
func _ready():
	DialogueManager.get_current_scene = func() -> Node:
		return MySceneManager.get_active_scene()
The built-in implementation looks at get_tree().current_scene before assuming the last child of get_tree().root is the current scene.

Generating Dialogue at Runtime

Create dialogue resources dynamically using create_resource_from_text():
var dialogue_text = """
~ greeting
Merchant: Welcome to my shop!
- What do you sell?
	Merchant: I have potions and weapons.
- Goodbye
	Merchant: Come back soon!
"""

var resource = DialogueManager.create_resource_from_text(dialogue_text)
if resource:
	var line = await resource.get_next_dialogue_line("greeting")
	show_dialogue(line)
The method will fail if there are syntax errors in the dialogue text. The resource is ephemeral and won’t be saved to disk.

DialogueManager Signals

Listen to these signals for advanced integration:
func _ready():
	DialogueManager.dialogue_started.connect(_on_dialogue_started)
	DialogueManager.dialogue_ended.connect(_on_dialogue_ended)
	DialogueManager.got_dialogue.connect(_on_got_dialogue)
	DialogueManager.mutated.connect(_on_mutated)

func _on_dialogue_started(resource: DialogueResource):
	print("Dialogue started: ", resource.resource_path)

func _on_dialogue_ended(resource: DialogueResource):
	print("Dialogue ended: ", resource.resource_path)

func _on_got_dialogue(line: DialogueLine):
	print("Got line: ", line.text)

func _on_mutated(mutation: Dictionary):
	print("Mutation executed")

Next Steps

Dialogue Label

Learn about the DialogueLabel node for typing effects

Custom Balloons

Create custom dialogue UI for your game

Build docs developers (and LLMs) love