.CurrentAnimationLength returns wrong length

Godot Version

v4.2.2.stable.mono.official [15073afe3]

Question

Hi there, first project in godot, i hope you can help me :slightly_smiling_face:
I’m working on a little top down game with currently 3 animations: idle, run and roll. I use an AnimationPlayer and I need the length of my animation in order to set the activeTime of my skills. For example my skill roll should last as long as its animation. GD.Print(currentAnimation) tells me that the animation never changes, it’s always “player_idle/player_idle_down”. the frames are changing and correct but the animation length is always the length of the idle animation.
Do I need to key the time aswell? And how can that be achieved?

AnimationController class:

using Godot;
using System;
using System.Collections.Generic;

public enum Skills{NO_STATE, IDLE, RUN, ROLL, DASH, BACKHOP};

public partial class AnimationController : AnimationPlayer
{
	Skills state = Skills.IDLE;
	int direction = 0;
	String[] directionArray = null;

	static String[] IdleDirections = {"player_idle/player_idle_up", "player_idle/player_idle_up_right","player_idle/player_idle_right","player_idle/player_idle_down_right", "player_idle/player_idle_down","player_idle/player_idle_down_left", "player_idle/player_idle_left","player_idle/player_idle_up_left"};
	static String[] RunDirections = {"player_run/player_run_up", "player_run/player_run_up_right","player_run/player_run_right","player_run/player_run_down_right", "player_run/player_run_down","player_run/player_run_down_left", "player_run/player_run_left","player_run/player_run_up_left"};
	static String[] RollDirections = {"player_roll/player_roll_up", "player_roll/player_roll_up_right", "player_roll/player_roll_right", "player_roll/player_roll_down_right", "player_roll/player_roll_down", "player_roll/player_roll_down_left", "player_roll/player_roll_left", "player_roll/player_roll_up_left"};
	// Called when the node enters the scene tree for the first time.
	public override void _Ready()
	{
		SetAnimation(state);
	}

	// Called every frame. 'delta' is the elapsed time since the previous frame.
	public override void _Process(double delta)
	{
		PlayAnimation();
	}

	void PlayAnimation()
	{
		if (directionArray != null)
		{
			Play(directionArray[direction]);
		}
	}
	public void SetAnimation(Skills state)
	{
		if (state == Skills.ROLL)
		{
			this.state = Skills.ROLL;
			directionArray = RollDirections;
		}
			
		else if (state == Skills.RUN)
		{
			this.state = Skills.RUN;
			directionArray = RunDirections;
		}
			
		else if (state == Skills.IDLE)
		{
			this.state = Skills.IDLE;
			directionArray = IdleDirections;
		}
		direction = DirectionToIndex(8);	
	}
	int DirectionToIndex(int sliceCount)
	{
		Vector2 dir = GetParent<PlayerController>().GetDirection();
		float step = (float)(360/sliceCount);
		float angle = Vector2.Up.AngleTo(dir);
		angle = (float)(angle * (180/3.1415926));
		if (angle < 0)
		{
			angle += 360;
		}
		float stepCount = angle/step;

		if (stepCount > 7.5)
		{
			stepCount = 0;
		}
		return (int)stepCount;
	}
}

_Process function in SkillManager:

public override void _Process(double delta)
    {
        if (skills != null)
        {
            for (int i = 0; i < skills.Count; i++)
            {
                switch (skills[i].GetState())
                {
                    case Skill.State.READY:
                    
                        if (Input.IsActionJustPressed(skills[i].GetKey()) && !skillIsActive)
                        {
                            skillIsInterruptable = skills[i].GetIsInterruptable();
                            skillIsActive = true;
                            skills[i].Use(GetParent<PlayerController>());
                            activeTime = skills[i].GetActiveTime();
                            skills[i].SetState(Skill.State.ACTIVE);
                        }
                        break;
                    case Skill.State.ACTIVE:
                        if (activeTime > 0)
                        {
                            activeTime -= delta;
                        }
                        else
                        {
                            skillIsInterruptable = true;
							skillIsActive = false;
							cooldownTime = skills[i].GetCooldownTime();
							skills[i].SetState(Skill.State.COOLDOWN);
                        }
                        break;
                    case Skill.State.COOLDOWN:
                        if (cooldownTime > 0)
                        {
                            cooldownTime -= delta;
                        }
                        else
                        {
                            skills[i].SetState(Skill.State.READY);
                        }
                        break;
                }
            }
        }
        if (!skillIsActive! || skillIsInterruptable)
        {
            if (GetParent<PlayerController>().GetIsMoving())
            {
                run.Use(GetParent<PlayerController>());
            }
            else
            {
                idle.Use(GetParent<PlayerController>());
            }
        }
    }

Use method in Roll class:

public override void Use(PlayerController player)
	{
		player.GetNode<AnimationController>("AnimationPlayer").SetAnimation(Skills.ROLL);
		activeTime = player.GetNode<AnimationPlayer>("AnimationPlayer").CurrentAnimationLength;
	}

Maybe animation change in next frame.
you can try use Signal CurrentAnimationChanged or AnimationChanged

1 Like

The Problem seems to be that the animation never changes. Although the animation plays the right frames, the name and the length always stay "player_idle/player_idle_down
and 2 seconds (which is the default animation). I only use AnimationPlayer. No AnimatedFrames and no AnimationTree.
Thanks for the reply.

Update: My mistake, I finally found the problem.
In the Use function I set the animation and than in the next line get it’s length via GetCurrentAnimationLength. The Problem is that i just change my enum state, the PlayAnimation function is later called in _process. So the animation isn’t changed yet and I get the length of either idle or run.