Having problems with animated sprite and freeing the scene on animation complete

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

I have not run into this issue yet and I’m on day 2 of trying to solve it, so I’ve gotta come ask.

I have a player that when you press Z, will attack with a sword. I have my sword scene, which is a node2d with an animated sprite. That sprite has 7 frames. My script code for it is as basic as it gets for the moment, I play the sprite on _ready and a signal is attached to free the object when the animation completes.

It does not work, however. If I remove queue_free from the animation_complete signal and set the sprite to loop, it plays fine, otherwise it does not show at all. It seems like it’s instantly being completed as soon as it’s ready.

What could be the issue here? I have a ton of other scenes and all the animations work fine, I’m not sure why this one being so simple is being a problem. Here is the sword script:

extends Node2D

func _ready():
	$AnimatedSprite.play('default')
	$AnimatedSprite.connect('animation_finished', self, '_on_animation_finished')

func _on_animation_finished():
	print('finished')
	queue_free()

Simple. With queue_free() removed and the animated sprite set to loop, I can use it in my main scene fine (although it loops forever), and I can f6 and test and see it. Otherwise, even testing the scene alone, nothing shows up.

:bust_in_silhouette: Reply From: Silvallis

Have you checked that the current animation position is set properly? If it would be at the end of the animation it would send the finished signal immediately and then free the scene.

Make sure that in the Animationplayer the current animation position is set all the way to the start.

:bust_in_silhouette: Reply From: njamster

_ready() will be called once all child-nodes are initialized and have entered the tree (see here). However, that is not necessarily the same moment, it appears on your screen! So if your animation is rather short and played with high FPS, it likely starts and finishes before you get a chance to see any of it. That seems to be mostly an issue though, when playing the scene on its own (by pressing F6). So instancing the sword animation from the player scene should work fine as is. I’m not aware of a satisfactory solution for this issue, but as a workaround you could delay it:

func _ready():
    yield(get_tree().create_timer(0.5), "timeout")
    $AnimatedSprite.play('default')
    $AnimatedSprite.connect('animation_finished', self, '_on_animation_finished')