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 tick

18.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.finished

18.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