Odd behaviour with AnimationPlayer when it played a non-looping animation

Godot Version

v4.3.stable.mono.official [77dcf97d8]

Question

I have a really odd behaviour with my AnimationPlayer that I honestly never ran into before. I have a few very basic animations that animate a Sprite2D’s Frames, as well as change it’s Texture, HFrames and VFrames at the very first keyframe when changing from one animation to the other.
This works great, and has worked for me for a long time before, but today I ran into an issue I never discovered before just when I started to rework how my AI moves, so I wanted to start simple and just rework it’s basic animation states. Here’s the code I have for it so far:

using System;
using Godot;

namespace GameName.Scripts.Entities.AI;

public partial class AiAnimationController : AnimationPlayer
{
    [Export] private GameCharacterEntity _character;

    public override void _Process(double delta)
    {
        base._Process(delta);

        Action transitionAction = GetTransitionAction();
        transitionAction?.Invoke();
    }

    private void PlayIfNotPlaying(string animationName)
    {
        if (CurrentAnimation != animationName)
        {
            Play(animationName);
        }
    }

    private Action GetTransitionAction()
    {
        return CurrentAnimation switch
        {
            "Idle" when Math.Abs(_character.Velocity.X) > 0 =>
                () => PlayIfNotPlaying("Walk"),
            "Walk" when Math.Abs(_character.Velocity.X) == 0 =>
                () => PlayIfNotPlaying("Idle"),
            
            ("Walk" or "Idle") when !_character.IsOnFloor() && _character.Velocity.Y < 0 =>
                () => PlayIfNotPlaying("Jump"),
            
            ("Walk" or "Idle") when !_character.IsOnFloor() && _character.Velocity.Y > 0 =>
                () => PlayIfNotPlaying("FallLoop"),
            
            "Jump" when !_character.IsOnFloor() && _character.Velocity.Y >= 0 =>
                () => PlayIfNotPlaying("FallInit"),
            
            "FallInit" when Math.Abs(CurrentAnimationLength - CurrentAnimationPosition) < 0.2 =>
                () => PlayIfNotPlaying("FallLoop"),
            
            ("FallInit" or "FallLoop" or "Jump") when _character.IsOnFloor() =>
                () => PlayIfNotPlaying("Idle"),
            
            _ => () => { }
        };
    }
}

What I noticed is that this works great, up until I play an animation that was non-looping, such as the jump animation. As soon as that happens, no matter how I call the Play() method afterwards, no other animations will ever play, and it’ll be stuck on the last frame of the animation that wasn’t set to loop.

Is this intended behaviour or am I missing something?

1 Like

Having dealt with this class before, it intuitively feels like a regression.

Like the main timer/delta was not reset internally that plays the animation player.

It certainly looks like it, as the last issue that referenced this was closed back in 2023.