Stuck on first frame of Run Cycle

Godot Version

4.5

Question

Hello, I am working on a 2D action platformer and after I added an attack button, the character's walk cycle is stuck on the first frame and I am unsure of how to proceed. This is the script I have currently

extends CharacterBody2D
@onready var animated_sprite_2d: AnimatedSprite2D = $AnimatedSprite2D

const SPEED = 850.0
@export var jump_velocity : float = -1500.0

var isAttacking: bool = false;

func _physics_process(delta: float) → void:
if isAttacking:
return

# add animation
if velocity.x > 1 or velocity.x <-1:
			animated_sprite_2d.animation = "Run"
else:
	animated_sprite_2d.animation = "Idle"
	
# Add the gravity.
if not is_on_floor():
	velocity += get_gravity() * delta
	animated_sprite_2d.animation = "Jump"
	

# Handle jump.
if Input.is_action_just_pressed("jump") and is_on_floor():
	velocity.y = jump_velocity

# Get the input direction and handle the movement/deceleration.
# As good practice, you should replace UI actions with custom gameplay actions.
var direction := Input.get_axis("left", "right") 
if direction:
	velocity.x = direction * SPEED
else:
	velocity.x = move_toward(velocity.x, 0, SPEED)

move_and_slide()
#attack
if Input.is_action_just_pressed("attack") and not isAttacking:
	$AnimatedSprite2D.play("Attack_1")
	isAttacking = true;
if direction == 1.0:
	animated_sprite_2d.flip_h = false
elif direction == -1.0:
	animated_sprite_2d.flip_h = true
	
	if isAttacking:
		velocity = Vector2.ZERO

func _on_animated_sprite_2d_animation_finished() → void:

if $AnimatedSprite2D.animation == "Attack_1":
	isAttacking = false;

What happens if you comment out all of the attack code?

No where in this script do you seem to play any animations other than Attack_1.

I’ve not used AnimatedSprite2D but presumably you need to play either Run or Idle animations once the attack is finished somewhere.

Have you checked out the official docs?

1 Like

The run animation plays up until Action 1 is pressed, afterwards the run animation is stuck on its first frame. Idle is fine(its one frame) and so is jump, pressing action 1 plays its animation like normal, only run is affected

As @gentlemanhal already said, you need to call play() on the sprite. Only assigning the animation will just get it stuck on the first frame.

1 Like

Where would I type play() on the script if you don’t mind me asking, I’m still not fully familiar with everything yet

Wherever you change the animation.

1 Like

Why you’re not using a state machine?. Something like:

enum Status {Idle, Moving, Shooting, Hurt, Dead}
var PlayerStatus: Status = Status.Idle

func _physics_process(delta: float) -> void:
		
	match PlayerStatus:
		Status.Idle:			
			$PlayerAnimation.play("Idle")
			if Input.is_action_pressed("ui_left") or Input.is_action_pressed("ui_right"):
				PlayerStatus = Status.Moving
			if Input.is_action_just_pressed("ui_accept") and PlayerStatus != Status.Shooting:				
				PlayerStatus = Status.Shooting
				
		Status.Moving:
			$PlayerAnimation.play("Move")
			PlayerDirection = Input.get_axis("ui_left", "ui_right")
			velocity.x = PlayerDirection * Speed 
			$PlayerAnimation.flip_h = PlayerDirection > 0
			if not Input.is_action_pressed("ui_left") and not Input.is_action_pressed("ui_right"):
				PlayerStatus = Status.Idle
			if Input.is_action_just_pressed("ui_accept") and PlayerStatus != Status.Shooting:
				PlayerStatus = Status.Shooting
				Shoot_Arrow()
		Status.Shooting:
			$PlayerAnimation.play("Shoot")
			await get_tree().create_timer(0.08).timeout
			PlayerStatus = Status.Idle
		Status.Hurt:
			$PlayerAnimation.play("Hurt")			
			PlayerStatus = Status.Idle
		Status.Dead:
			pass

Instead of typing animated_sprite_2d.animation = “Run”, try animated_sprite_2d.play(“Run”)

If you nest your animations under different conditions you may get the results better too, like this:

if is_on_floor(): # Only play these animations if you're on the floor
		if direction == 0: # Sit idle if you're not moving
			animated_sprite_2d.play("Idle")
		else: # Run otherwise
			animated_sprite_2d.play("Run")
	else: # If you're not on the ground, you must be jumping/falling
		animated_sprite_2d.play("Jump")
		velocity += get_gravity() * delta
1 Like