Unable to connect Tween's "finished" signal from child node to parent node

Godot Version

Godot Engine v4.2.2.stable.official

Question

`This is for a 3D game. Under the main Node3D I have a child Camera3D node to which I have attached a script. In that script I created a Tween. The Tween animation is written in _ready() of the child node script. I want to connect the finished signal of the Tween to the main Node3D script but I get this error

"E 0:00:01:0029 main.gd:95 @ _ready(): In Object of type ‘Camera3D’: Attempt to connect nonexistent signal ‘finished’ to callable ‘Node3D(main.gd)::_on_player_view_camera_loading_camera_animation_done’.
<C++ Error> Condition “!signal_is_valid” is true. Returning: ERR_INVALID_PARAMETER
<C++ Source> core/object/object.cpp:1344 @ connect()
main.gd:95 @ _ready()
" `

Please help.

Here is the relevant code snippet:


I think you need to use something like this instead of trying to emit a signal “finished” (which is not a tween method btw) :

	tween.tween_callback(_your_method_here)

This will call a method when the tween is finished. The docs on tweens are excellent BTW.

Or you can used the tween finished signal:

tween.connect("finished", _your_method_here)

Or await for the finished signal and proceed with whatever:

await tween.finished
your_signal.emit()

Hope that helps,

Paul

PS I still emit signals the old way and a SignalManager autoload. Perhaps I should update this:

SignalManager.emit_signal("screen_message_completed")

Hey Thanks for the reply Paul.

Actually, I’m able to get the desired behavior when I comment lines 95, and 9. Then uncomment line 10.
In line 10, I’m able to use finished signal to call xxx_animation_done() in parent node. But I think this isn’t the right way to do it.

Following Observer pattern, I want the Camera3D node to just emit the signal and not care about who uses it. That is, I want to do the signal to function binding at the destination, which here is the parent node script.

I’m not able to do it. Line 95 always throws the error that the signal doesn’t exist.

If you could tell me how to do it in the parent script, that would be great!

-Amit

Personally I would not do that. I don’t like the tight coupling. However perhaps your camera is not a separate scene.

The problem with line 95 is that you are trying to connect to the finished signal. The only signal you have there is line 2 signal.

If I have understood you correctly, line 9 could be (and there are different ways of doing this):

tween.tween_callback(_on_tween_finished)

This callback will be fired when your tween is finished.
Then add a new function in this script something like this:

func _on_tween_finished():
    loadingCameraAnimationDone.emit()

Then in your main script or wherever you want, you need to connect to the signal you have just emitted. So line 95 would be:

$PlayerViewCamera.loadingCameraAnimationDone.connect(_on_my_long_method_name)

When it gets the signal it will connect to whatever callable you have put in there, in this case ‘_on_my_long_method_name’

So when your camera gets the signal finished, it emits the custom signal loadingCameraAnimationDone. You main script is now connected to that signal and calls its own method func _on_my_long_method_name()

Your signal I would call camera_ready, not loadingCameraAnimationDone. Then you connected method could be simply _on_camera_ready() which is a lot more readable. Personal preference I suppose.

Best wishes,

Paul

PS if you use this:

@onready var Camera = $PlayerViewCamera

Then you calls are even more readable.

# Better signal name
signal camera_ready

func _on_tween_finished():
    camera_ready.emit()

# Better variable names
Camera.camera_ready.connect(_on_camera_ready)


Thanks a lot Paul. I followed the exact steps you mentioned and it works perfectly. Your solution is what I wanted to go for.

Thanks for the quick replies too
<3

-Amit

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.