【Godot4】awaitで関数の終了まで待つ方法(コルーチンの使い方)
2026-08-04
私は現在カードゲームを作成しているのですが、カードゲームでは様々な効果を表現する演出が必要になります。
演出によって待つ時間も異なるため、カードの効果を発動させる関数内で、awaitを使って違う秒数を待つ動作を実装しました。
しかし、関数内でawaitを使っても、関数の呼び出し元は止まっていないらしく、思った通りの動きをしてくれませんでした。
この記事では、非同期の関数を呼び出し元でも await 関数名() と書くことで、その関数の終了まで待つ方法について解説します。
環境
- Godot4.7
- GDScript
具体例
話を簡単にするために、指定の文字を特定の秒数表示する演出を2連続で実行するときを考えます。
引数に応じて指定の文字を特定の秒数表示するshow_text()関数があります。
func show_text(n:int) -> void:
var text = "" # 表示文字列
var t = 0.0 # 表示時間
match n:
1:
text = "3秒待ってね"
t = 3.0
2:
text = "スタート"
t = 5.0
$Label.text = text
# 表示する
$Label.show()
# t秒待つ
await get_tree().create_timer(t).timeout
# 表示を消す
$Label.hide()
この関数を呼び出して処理をします。
func _ready() -> void:
show_text(1)
show_text(2)
このコードの意図としては"3秒待ってね”が3秒間表示された後に”スタート”が5秒間表示されてほしいが、 実行すると、こうなります。
"3秒待ってね”は表示されず、”スタート”が表示され、3秒で消えてしまいます。
show_text(1)をそのまま呼び出した場合、await で3秒待つ命令が完了する前に、呼び出し元の_ready()の次の命令show_text(2) が実行されます。
そのため表示文字列が書き換えられてしまい、"3秒待ってね”が表示されません。
しかし、show_text(1) の実行がなくなったわけではないので3秒後に文字の表示が消えてしまいます。
呼び出し元の_ready() 内で特定の秒数待つことにより、意図通りの動きにすることもできるが、その場合は以下のようなコードになります。
func _ready() -> void:
var n = 1
show_text(n)
if n == 1:
await get_tree().create_timer(3.0).timeout
elif n == 2:
await get_tree().create_timer(5.0).timeout
n = 2
show_text(n)
if n == 1:
await get_tree().create_timer(3.0).timeout
elif n == 2:
await get_tree().create_timer(5.0).timeout
このコードではshow_text() を呼び出すたびにnの種類の数だけif 文を書かないといけないのでコードが長くなってしまいます。
さらに、待つ時間を変えたい場合に関数内だけでなく、すべての呼び出し元を修正しなければならないので大変です。
解決方法(awaitで関数の終了まで待つ)
以下のようにする。関数の呼び出しの前にawaitをつけます。
func _ready() -> void:
await show_text(1)
await show_text(2)
awaitを使っている関数は、一般にコルーチンとして扱われます。この場合はshow_text() がコルーチンになっています。
await はtimeout やpressed などのシグナルを待つ用途で使われることが多いため、シグナルしか待てないと思っていました。
awaitはシグナルだけでなく、コルーチンを待つこともできます。
つまり、show_text() を呼び出すときに、await show_text() と書くことでshow_text() の実行終了まで待つことができます。
await をつけたことで以下の動画のように正しい順序で実行されています。
まとめ
awaitを使っている関数は、コルーチンとして扱われます。
その関数をただ呼び出しただけでは呼び出し元の実行は止まらないが、await 関数名() と書くことで、関数の終了まで待つことができる。💯