Hi!
I’m on Godot 4.2.2 and am experiencing a very weird bug with await
and signals.
I have a function called play_animation()
that takes in an enum and does different things depending on what enum is given. Sometimes it animates using an AnimationPlayer
and sometimes using a looped Tween
. This function emits the signal _animation_done
when the AnimationPlayer
is done or the Tween
has been created. The signal is awaited by load_character_data()
, so I emit the signal even when an endless Tween
is used so that the function can continue.
Now, when it uses the AnimationPlayer
, everything works fine. But when the Tween
is used, I get the following two errors and the rest of the function doesn’t get executed:
E 0:00:01:0360 dialogue_event.gd:68 @ play_animation(): Resumed function 'load_character_data()' after await, but script is gone. At script: res://screens/events/dialogue_event/dialogue_event.gd:37
<C++ Error> Method/function failed. Returning: Variant()
<C++ Source> modules/gdscript/gdscript_function.cpp:197 @ resume()
<Stack Trace> dialogue_event.gd:68 @ play_animation()
dialogue_event.gd:36 @ load_character_data()
dialogue_event.gd:20 @ <anonymous lambda>()
E 0:00:01:0360 dialogue_event.gd:20 @ <anonymous lambda>(): Attempt to disconnect a nonexistent connection from 'DialogueEvent:<Control#28538045649>'. Signal: '_animation_done', callable: 'GDScriptFunctionState::_signal_callback'.
<C++ Error> Condition "!s->slot_map.has(*p_callable.get_base_comparator())" is true. Returning: false
<C++ Source> core/object/object.cpp:1420 @ _disconnect()
<Stack Trace> dialogue_event.gd:20 @ <anonymous lambda>()
What do you mean the script is gone?! How’s that possible?
I did check the Remote tab and sure enough, the Node still exists:
And the script is attached:
Also, the second error references a lamda that “redirects” the AnimationPlayer.animation_finished
signal to my own _animation_done
signal. I also think that that is the difference between using the AnimationPlayer
and a Tween
. When a Tween
is used, the signal gets emitted immediately (because the Tween
loops and therefor never ends, so I just emit it to continue with the rest of instructions). On the other hand AnimationPlayer
needs a few seconds until it’s done, and so the error doesn’t occur for whatever reason.
I tried waiting for a Timer
before emitting the signal when a Tween
is used, and look at that, it started working!
tween.play()
await get_tree().create_timer(1).timeout # I added this, and it stopped crashing.
_animation_done.emit()
So, technically everything works now. But this very much is a workaround and I’d like to know how to resolve this issue “properly”, and if this is a bug then I’m probably gonna report it then.