This example demonstrates the most basic usage of the Dialogue Engine: creating a simple linear dialogue with multiple text entries and connecting to signals to display them.
Overview
In this example, you’ll learn how to:
Create a DialogueEngine instance
Add text entries with BBCode formatting
Connect to dialogue signals
Advance through dialogue
Display dialogue in the UI
Setting Up the Dialogue
First, let’s create a DialogueEngine by extending it and adding text entries in the _setup() method:
extends DialogueEngine
func _setup () -> void :
add_text_entry ( "Hey..." )
add_text_entry ( "[i]Have [i][b]you[/b][/i] seen the code for this sample?[/i]" )
add_text_entry ( "[rainbow freq=1.0 sat=0.4 val=0.8]It's beautiful![/rainbow]" )
add_text_entry ( "[i][shake rate=20.0 level=5 connected=1]You won't believe it![/shake][/i]" )
add_text_entry ( "[code][i]Press <Enter> or <Space> to exit.[/i][/code]" )
The _setup() method is automatically called when the DialogueEngine is instantiated. This is the recommended place to build your dialogue tree.
BBCode Support
Notice that the dialogue entries use BBCode tags for rich text formatting:
[i] for italic text
[b] for bold text
[rainbow] for rainbow color effect
[shake] for shaking text effect
[code] for monospace font
DialogueEngine text entries support all BBCode tags that Godot’s RichTextLabel supports. This includes colors, fonts, images, and custom effects.
Creating the UI
Now let’s create the UI script that displays the dialogue:
extends VBoxContainer
@export var dialogue_gdscript : GDScript = null
var dialogue_engine : DialogueEngine = null
func _ready () -> void :
dialogue_engine = dialogue_gdscript . new ()
dialogue_engine . dialogue_started . connect ( __on_dialogue_started )
dialogue_engine . dialogue_continued . connect ( __on_dialogue_continued )
dialogue_engine . dialogue_finished . connect ( __on_dialogue_finished )
func _input ( p_input_event : InputEvent ) -> void :
if p_input_event . is_action_pressed ( & "ui_accept" ):
dialogue_engine . advance ()
func __on_dialogue_started () -> void :
print ( "Dialogue Started!" )
func __on_dialogue_continued ( p_dialogue_entry : DialogueEntry ) -> void :
var label : RichTextLabel = RichTextLabel . new ()
label . set_use_bbcode ( true )
label . set_fit_content ( true )
label . set_text ( " > " + p_dialogue_entry . get_text ())
add_child ( label )
func __on_dialogue_finished () -> void :
print ( "Dialogue Finished! Exiting..." )
get_tree (). quit ()
Code Breakdown
1. Setting Up the Engine
@export var dialogue_gdscript : GDScript = null
var dialogue_engine : DialogueEngine = null
func _ready () -> void :
dialogue_engine = dialogue_gdscript . new ()
The dialogue GDScript is exported so you can assign it in the Godot editor. When the node is ready, we instantiate the DialogueEngine.
2. Connecting to Signals
dialogue_engine . dialogue_started . connect ( __on_dialogue_started )
dialogue_engine . dialogue_continued . connect ( __on_dialogue_continued )
dialogue_engine . dialogue_finished . connect ( __on_dialogue_finished )
We connect to three key signals:
dialogue_started: Emitted when dialogue begins
dialogue_continued: Emitted for each text entry (this is where we display text)
dialogue_finished: Emitted when dialogue ends
3. Advancing the Dialogue
func _input ( p_input_event : InputEvent ) -> void :
if p_input_event . is_action_pressed ( & "ui_accept" ):
dialogue_engine . advance ()
Each time the player presses Enter or Space, we call advance() to move to the next dialogue entry.
4. Displaying the Text
func __on_dialogue_continued ( p_dialogue_entry : DialogueEntry ) -> void :
var label : RichTextLabel = RichTextLabel . new ()
label . set_use_bbcode ( true )
label . set_fit_content ( true )
label . set_text ( " > " + p_dialogue_entry . get_text ())
add_child ( label )
For each dialogue entry, we create a new RichTextLabel to display the text with BBCode formatting enabled.
In a real game, you would typically reuse a single label and update its text, rather than creating new labels. This example creates new labels for demonstration purposes.
Dialogue Flow
Here’s how the dialogue progresses:
Player starts the game
Press Enter/Space → dialogue_started emits, first entry displays: “Hey…”
Press Enter/Space → Second entry displays: “Have you seen the code…”
Press Enter/Space → Third entry displays: “It’s beautiful!”
Press Enter/Space → Fourth entry displays: “You won’t believe it!”
Press Enter/Space → Fifth entry displays: “Press Enter or Space to exit.”
Press Enter/Space → dialogue_finished emits, game exits
Press Enter/Space again → Dialogue restarts from the beginning
Complete Example in One File
If you prefer to keep everything in a single script without extending DialogueEngine:
extends VBoxContainer
var dialogue_engine : DialogueEngine = null
func _ready () -> void :
# Create the dialogue engine
dialogue_engine = DialogueEngine . new ()
# Build the dialogue
dialogue_engine . add_text_entry ( "Hey..." )
dialogue_engine . add_text_entry ( "[i]Have you seen the code?[/i]" )
dialogue_engine . add_text_entry ( "[rainbow]It's beautiful![/rainbow]" )
dialogue_engine . add_text_entry ( "[shake]Amazing![/shake]" )
# Connect signals
dialogue_engine . dialogue_continued . connect ( __on_dialogue_continued )
dialogue_engine . dialogue_finished . connect ( __on_dialogue_finished )
func _input ( p_input_event : InputEvent ) -> void :
if p_input_event . is_action_pressed ( & "ui_accept" ):
dialogue_engine . advance ()
func __on_dialogue_continued ( p_dialogue_entry : DialogueEntry ) -> void :
var label : RichTextLabel = RichTextLabel . new ()
label . set_use_bbcode ( true )
label . set_fit_content ( true )
label . set_text ( " > " + p_dialogue_entry . get_text ())
add_child ( label )
func __on_dialogue_finished () -> void :
print ( "Dialogue Finished!" )
Key Takeaways
Use dialogue_continued to display text - This signal provides the DialogueEntry with all the text and metadata you need.
Call advance() to progress - The dialogue only moves forward when you explicitly call advance().
Enable BBCode for rich text - Set set_use_bbcode(true) on RichTextLabel to enable formatting.
Dialogue auto-restarts - After finishing, calling advance() again will restart the dialogue from the beginning.
Next Steps
Conditional Branching Learn how to create dialogue that branches based on conditions
Player Options Add player choices to your dialogue