Coroutines & await
await pauses the current function until a signal is emitted or another coroutine finishes, then resumes.
18.1 await basics
await pauses the current function until a signal is emitted or another coroutine finishes, then resumes. The rest of the game keeps running.
func _ready() -> void:
print("Start")
await get_tree().create_timer(1.5).timeout # wait 1.5 seconds
print("1.5 seconds later")
await $AnimationPlayer.animation_finished
print("Animation done")
await get_tree().process_frame # wait one frame
await get_tree().physics_frame # wait one physics tick18.2 Coroutines returning values
Any function containing await is a coroutine. Awaiting it waits for it to finish and gives its return value:
Calling a coroutine without await starts it and returns immediately at the first await (the result is discarded). The editor warns if you await a function that is not a coroutine.
func ask_question(text: String) -> bool:
$Dialog.show_question(text)
var answer: bool = await $Dialog.answered # signal answered(yes: bool)
return answer
func _on_shop_opened() -> void:
if await ask_question("Buy the sword?"):
buy("sword")18.3 Awaiting signals with arguments
No arguments → await returns null.
One argument → returns that value.
Several arguments → returns an Array of the values.
var anim_name: StringName = await $AnimationPlayer.animation_finished
var args: Array = await $HTTPRequest.request_completed # [result, code, headers, body]18.4 Sequences and cutscenes
func play_intro() -> void:
set_process_input(false)
await fade_in(1.0)
await say("Welcome, traveler.")
await move_camera_to($Castle.global_position, 2.0)
await say("The castle awaits.")
set_process_input(true)
func fade_in(duration: float) -> void:
var tween := create_tween()
tween.tween_property($Fade, "modulate:a", 0.0, duration)
await tween.finished18.5 Pitfalls
If the node is freed while awaiting a signal from another object, the function is abandoned when the awaited object dies; but awaiting a long timer and then touching a freed node causes errors — check is_instance_valid(self) / is_inside_tree() after long waits.
create_timer(t, process_always := true, process_in_physics := false, ignore_time_scale := false) — timers keep running during pause unless you pass false for process_always.
There is no built-in "await all"; start helper coroutines without await and count completions:
Godot 3 note: yield(obj, "signal") and GDScriptFunctionState were replaced by await.
func await_all(signals: Array[Signal]) -> void:
var state := {"remaining": signals.size()}
for s in signals:
_wait_one(s, state) # not awaited → runs concurrently
while state.remaining > 0:
await get_tree().process_frame
func _wait_one(s: Signal, state: Dictionary) -> void:
await s
state.remaining -= 1