Create time-limited dialogue choices with visual feedback and automatic fallbacks
This example demonstrates how to create dialogue options with time limits, showing a complete implementation with visual feedback, progress bars, and automatic option selection when time runs out.
extends DialogueEngineenum { DEFAULT_TOPIC = 0, WATCH_THE_STORM, GO_BACK_TO_SLEEP, KEEP_WORKING,}func _setup() -> void: var entry: DialogueEntry = add_text_entry("The storm rages right outside the window. I should...") var option_id_1: int = entry.add_option("Wait for storm to finish.") var option_id_2: int = entry.add_option("Go back to sleep.") var option_id_3: int = entry.add_option("Get back to work.") var option_id_4: int = entry.add_option("Hidden option -- this should not be shown on the UI") entry.set_metadata("dont_show_options", [option_id_4]) entry.set_metadata("auto_choose", option_id_4) var option_id_2_entry: DialogueEntry = add_text_entry("That's right, sleep is for the strong 💪.", GO_BACK_TO_SLEEP) entry.set_option_goto_id(option_id_2, option_id_2_entry.get_id()) var option_id_3_entry: DialogueEntry = add_text_entry("That's right, let's get back to work 🫡", KEEP_WORKING) entry.set_option_goto_id(option_id_3, option_id_3_entry.get_id()) var option_id_4_entry: DialogueEntry = add_text_entry("I think I'll enjoy watching the storm for a bit...", WATCH_THE_STORM) entry.set_option_goto_id(option_id_4, option_id_4_entry.get_id()) # Join branches into the default topic var default_topic: DialogueEntry = add_text_entry("Some time passes...") entry.set_option_goto_id(option_id_1, default_topic.get_id()) option_id_2_entry.set_goto_id(default_topic.get_id()) option_id_3_entry.set_goto_id(default_topic.get_id()) option_id_4_entry.set_goto_id(default_topic.get_id()) add_text_entry("<Press 'Space' or 'Enter' to quit>")
The dialogue structure is similar to the animations example, but the UI implementation adds time-based mechanics.
if option_id == 1: tween.tween_callback(button.grab_focus) tween.tween_callback(progress_bar.show) tween.tween_method(progress_bar.set_value, 1.0, 0.0, 2.0) # The timer has just finished tween.tween_callback(progress_bar.hide) tween.tween_callback(advance_dialogue_no_answer)
When the second option becomes visible:
Focus the button
Show the progress bar
Animate progress bar from 100% to 0% over 2 seconds
Hide the progress bar
Call the timeout handler
tween_method is perfect for animating property values over time, like progress bars or health bars.
func advance_dialogue_no_answer() -> void: for button: Button in enabled_buttons: button.set_disabled(true) var entry: DialogueEntry = dialogue_engine.get_current_entry() var option_id: int = entry.get_metadata("auto_choose") entry.choose_option(option_id) dialogue_engine.advance() set_process_input(true)
func __advance_dialogue_with_chosen_option(p_option_id: int) -> void: # Kill all tweens from processing further for tween: Tween in get_tree().get_processed_tweens(): tween.kill() for button: Button in enabled_buttons: button.set_disabled(true) # Reset modulate of vanishing button button.modulate = Color.WHITE enabled_buttons.clear() progress_bar.hide() var current_entry: DialogueEntry = dialogue_engine.get_current_entry() current_entry.choose_option(p_option_id) dialogue_engine.advance() set_process_input(true)
When the player clicks a button:
Kill all tweens - Stop the timer and animations
Disable and reset all buttons
Hide the progress bar
Select the chosen option
Advance the dialogue
Always kill active tweens when the player makes a choice, or they’ll continue running and may trigger the timeout callback even after the player has made a selection.
0.0s: Options appear - Option 0: "Wait for storm to finish" (visible, focused, fading) - Option 1: "Go back to sleep" (hidden) - Option 2: "Get back to work" (hidden)3.0s: Option 0 fully faded and hidden5.0s: Options 1 and 2 appear - Option 1 gains focus - Progress bar appears at 100%5.0s - 7.0s: Progress bar animates from 100% to 0%7.0s: Timeout - Progress bar hides - Auto-select hidden option 4 - Dialogue advances to "watching the storm" branch
Use metadata to set different time limits for different choices:
func _setup() -> void: var entry: DialogueEntry = add_text_entry("Quick! What do you do?") entry.add_option("Dodge!") entry.add_option("Block!") entry.add_option("Counter!") entry.set_metadata("time_limit", 3.0) # 3 seconds to choose entry.set_metadata("auto_choose", 1) # Default to "Block"
func __on_dialogue_continued(entry: DialogueEntry) -> void: if entry.has_options(): var time_limit = entry.get_metadata("time_limit", 10.0) start_timer(time_limit)
func start_timer_with_audio(duration: float) -> void: var tween = create_tween() tween.tween_method(progress_bar.set_value, 1.0, 0.0, duration) # Play tick sounds every second for i in range(int(duration)): tween.parallel().tween_callback(play_tick_sound).set_delay(float(i)) # Play final beep before timeout tween.tween_callback(play_timeout_sound).set_delay(duration - 0.5) tween.tween_callback(on_timeout)