AnimationPlayer plays extra frame after moving Player to a specific location

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

I’m working on my first game, a plataformer 2d. I want to implement a ledge climb for the Player, so when they detect a ledge, they can climb it. The AnimationPlayer plays the climb_ledge animation, and once it finishes, I move the Player to a specific location (in this case the tile that’s up the ledge). This is the specific portion of the code:

CLIMB_LEDGE:
			var target = ledge_climb_pos.get_global_position() 
			animation_player.play("Climb_Ledge")
			yield(get_node("AnimationPlayer"), "animation_finished")
			position = target
		    state = WALK

ledge_climb_pos is an Area2d that’s a child of the KinematicBody2d set at the specific place where the sprite ends at the end of the animation: frames hosted at ImgBB — ImgBB

frames

AnimationPlayer.play("Climb_Ledge)

(“reference frame” is not part of the animation, is just to illustrate where the Player should end up) After yield, I set the position of the Player to that target location. It works, but there is an extra frame of the animation that appears for a fraction of a second, as if the next animation (in this case an Idle) started playing at the target’s previous location before setting the new location.
Here’s a video that illustrates what I mean: https://youtu.be/_eRdaubooVo

I hope this is clear. English is not my first language.

Thanks in advance!

:bust_in_silhouette: Reply From: li_fran

On a closer inspection, there is no extra frame being played. What happens is that the Animation Player gets to the last frame of the animation (the third one on the image I shared), then the position is reseted while the frame is still visible, and then the next animation begins playing. Still don’t know how to solve it, though

:bust_in_silhouette: Reply From: li_fran

Ok! So I think I figured it out. AnimationPlayer has a void method called advance. This is the description in the documentation:

void advance ( float delta )
Shifts position in the animation timeline and immediately updates the animation. delta is the time in seconds to shift. Events between the current frame and delta are handled.

To be honest, I don’t fully understand how or why this works, but I changed the code to:

CLIMB_LEDGE:
    var target = ledge_climb_pos.get_global_position()                      
    animation_player.play("Climb_Ledge")                  
    yield(animation_player, "animation_finished")   
    animation_player.advance(delta)     #THIS IS THE ADDED LINE       
    position = target  
    state = WALK

… and now the position seems to be updated correctly, in between the last frame of the “Climb_Ledge” animation and the first of the “Idle” animation. I then just had to turn the Smoothing property of the Camera2D to “Enabled” so the camera doesn’t jump between the old and new positions, and this is how it looks: https://youtu.be/SsgSHFhdNyY

Hope this is helpful to someone else :slight_smile: Thanks!