Dynamically generating tween animations

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By maser


In the example above I have two custom animations, A and C. They both start and end at completely different positions.

At the end of animation A, I want Godot to automatically generate a new animation, B, that transitions to the first frame of C. Importantly, I need to be able to trigger that new animation at any point during the lifecycle of animation A, whether it just started, is halfway through, or is at the end. Ideally there would be a crossfade between A and B as B becomes active.

I’ve spent a good couple of hours crawling through the docs and messing around with AnimationTree and I’m getting nowhere. Does anyone know if there’s a way to do this natively in Godot?

:bust_in_silhouette: Reply From: hammeron

In the animation editor in the AnimationPlayer, click Animation → Edit Transitions to set cross-animation blending. You can overwrite the blending when calling AnimationPlayer.play() too.
The value is how much time the animation will take to have 100% effect. If A is playing, then C starts and its blend time is 0.5; it will take half a second to completely switch to C.

func go_from_A_to_C() -> void:
	#Start C after 300 milliseconds
	var timer = get_tree().create_timer(0.3)
	yield(timer, "timeout")
	$AnimationPlayer.play("C", 0.5)

I might be misunderstanding you, but isn’t this just going to blend the two animations? Ie. animation C will start immediately before animation A has finished, and the blend will just some mixture of the two.

My use case is that A finishes at some point in its lifecycle, animation B begins and finishes, and then finally animation C starts. Optionally, there would be some blending between A and B, and B and C.

The more I look into this more I’m starting to conclude that Godot just can’t do this, and I’m going to need to programmatically create and inject the intermediary animations using the Tween node.

maser | 2020-04-25 03:30

You misunderstand the purpose of the code. play(C) doesn’t execute soon after play(A). The yield(timer, “timeout”) line freezes the function’s execution and waits for a timer of 0.3 seconds to finish to resume execution. Because of it, $AnimationPlayer.play(“C”, 0.5) is executed 0.3 seconds after $AnimationPlayer.play(“A”).

Take a look at Coroutines with yield. Particularly, Coroutines & signals. It’s my favorite GDScript feature because it simplifies a lot the coding of a sequence of actions that don’t happen at the same time.

hammeron | 2020-04-25 13:48