How to wait for tweens in Godot 4
Asked Answered
H

3

5

Previously, in Godot 3.1 I had something like this to wait for a Tween animation to finish:

await current_screen.tween.tween_completed

Where the tween was a node of the current_screen. Now, as I understand it, we are supposed to create the tween just when we need it (as the documentation suggests). This makes it so the current_screen does not have a tween node and thus no way to know if the tween created inside a function is completed or not.

How can I achieve the same behaviour as with tween_completed in Godot 4?

Handy answered 5/8, 2023 at 13:48 Comment(0)
B
5

You are correct, in Godot4 we normally instantiate a Tween programmatically and handle everything in code.

An easy way to run a process after the tween has completed is to connect to it's finished signal.

@onready var sprite: Sprite2D = $Sprite

func _ready():
    var tween = get_tree().create_tween()
    tween.tween_property(sprite, "position", Vector2(600, 600), 3)
    tween.connect("finished", on_tween_finished)
    
func on_tween_finished():
    print("Tween done!")

The on_tween_finished function will be called after the tween has been fully completed.

Here are some of the other signals one can use when working with Tweens: https://docs.godotengine.org/en/stable/classes/class_tween.html#signals

Bespatter answered 6/8, 2023 at 7:57 Comment(3)
Thanks for the reply. That should be it, but I do not seem to be able to use it in my specific case. I want to await for the finishing of the animation in a node that has another node that does that code. Previously I would do it like "await current_screen.tween.tween_completed". I do not want to implement a behaviour in the node that triggers the tweener.Handy
The problem is in this code: func change_screen(new_screen): if current_screen: current_screen.disappear() await current_screen.tween.tween_completed current_screen = new_screen if new_screen: current_screen.appear() await current_screen.tween.tween_completedHandy
Ah, I think I understand. If you want to wait for the current_screen's Tween completion from a completely separate node, perhaps you could emit a new signal from the current_screen when the tween's 'finished' signal has fired. If that doesn't work, a dumb way to do it would be to have a boolean property called 'finished_tweening' in the current_screen and set it to true after the tween's 'finished' signal has fired.Bespatter
K
12

Try:

var tween := create_tween()
tween.tween_property( … )
await tween.finished

tween.finished is a signal that you can listen to.

Kinswoman answered 19/10, 2023 at 17:35 Comment(0)
B
5

You are correct, in Godot4 we normally instantiate a Tween programmatically and handle everything in code.

An easy way to run a process after the tween has completed is to connect to it's finished signal.

@onready var sprite: Sprite2D = $Sprite

func _ready():
    var tween = get_tree().create_tween()
    tween.tween_property(sprite, "position", Vector2(600, 600), 3)
    tween.connect("finished", on_tween_finished)
    
func on_tween_finished():
    print("Tween done!")

The on_tween_finished function will be called after the tween has been fully completed.

Here are some of the other signals one can use when working with Tweens: https://docs.godotengine.org/en/stable/classes/class_tween.html#signals

Bespatter answered 6/8, 2023 at 7:57 Comment(3)
Thanks for the reply. That should be it, but I do not seem to be able to use it in my specific case. I want to await for the finishing of the animation in a node that has another node that does that code. Previously I would do it like "await current_screen.tween.tween_completed". I do not want to implement a behaviour in the node that triggers the tweener.Handy
The problem is in this code: func change_screen(new_screen): if current_screen: current_screen.disappear() await current_screen.tween.tween_completed current_screen = new_screen if new_screen: current_screen.appear() await current_screen.tween.tween_completedHandy
Ah, I think I understand. If you want to wait for the current_screen's Tween completion from a completely separate node, perhaps you could emit a new signal from the current_screen when the tween's 'finished' signal has fired. If that doesn't work, a dumb way to do it would be to have a boolean property called 'finished_tweening' in the current_screen and set it to true after the tween's 'finished' signal has fired.Bespatter
E
1

I just did this in C# this way ...

var tween = CreateTween();
tween.TweenProperty(mainImage, "modulate", new Color(1, 1, 1, 0), 1); //fade out
tween.TweenCallback(Callable.From(() => mainImage.Texture = texture)); //this waits for tween to finish before changing image
tween.TweenProperty(mainImage, "modulate", new Color(1, 1, 1, 1), 2); //fade in  
English answered 1/12, 2023 at 20:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.