AnimatedSprite2D node will not play animation on Input.Is_action_pressed()

Godot Version

4.0.2 stable

Question

I’m trying to run a group of animations on my sprite character. I’m using a AnimatedSprite2D, which frees me from using a AnimationPlayer for my animations. I have 8 animations, 4 idle animations corresponding to the 4 sides of the player and 4 running animations. The directions are up, down, left and right. So when I use the Input.Is_action_pressed() to point in a direction, the sprite doesn’t play that animation.

Example I run if Input.is_action_pressed(“ui_left”) it should run $AnimatedSprite2D.play(“Run_left”). I’ll paste my code here.

@onready var _animated_sprite = $AnimatedSprite2D

func _physics_process(_delta):
var velocity = Vector2.ZERO # The player’s movement vector.d

# go left and play animation
if Input.is_action_pressed("ui_left"):
	_animated_sprite.play("Run_left")
	velocity.x -= 1
else:
	_animated_sprite.play("Idle_left")	

# go right and play animation	
if Input.is_action_pressed("ui_right"):
	_animated_sprite.play("Run_right")
	velocity.x += 1
else:
	_animated_sprite.play("Idle_right")	

# go up and play animation	
if Input.is_action_pressed("ui_up"):
	_animated_sprite.play("Run_up")
	velocity.y -= 1
else:
	_animated_sprite.play("Idle_up")	

# go down and play animation	
if Input.is_action_pressed("ui_down"):
	_animated_sprite.play("Run_down")
	velocity.y += 1	
else:
	_animated_sprite.play("Idle_down")

Hi! This is a classic example of why you should separate your physics and animations into two separate sections! In your code, you’re changing the velocity depending on what key is being pressed. By trying to place the animation into this code, you are constantly changing animations depending on the key that has been pressed. For example, if I pressed ui_left, then the first block would check I am pressing it, and tell the sprite to play Run_left, but the next block would check I’m not pressing ui_Right, and tell the sprite to play Idle_right, and so on.

Try this:

func _process():
    if velocity != Vector2.ZERO:
        if velocity.x > 0:
            _animated_sprite.play("Run_left")
        elif velocity.x < 0:
            _animated_sprite.play("Run_right")
        etc...

It’s getting late where I am now, but I hope this makes sense! If not, I’ll try to explain more tomorrow.

3 Likes

Thank you. I’ll try this today. I thanks for looking at my code!

I believe the solution to this problem is not changing the code structuring, though I can’t speak to if it’s helpful for a game or not. I’m definitely going to try integrating that myself just to see what happens though lol.

I think the solution could simply be changing all of your Input.is_action_pressed() to Input.is_action_just_pressed()

1 Like

@greencloversgames has the right solution (plz mark their post as Solution, not mine), here I’ll just put the whole code together so it’s easier to consume since you’re new to godot. I’ve also added “speed” variable so you can control character speed manually or by changing speed somewhere else in code.

var speed := 1 # change this to make char faster/slower
var _last_direction := Vector2.ZERO # used to know which idle animation to play

func _ready():
	# play default animation based on default direction character is facing
	_animated_sprite.play("Idle_right")

func _process(_delta):
	if Input.is_action_pressed("ui_left"):
		velocity.x = speed * -1
	elif Input.is_action_pressed("ui_right"):
		velocity.x  = speed
	elif Input.is_action_pressed("ui_up"):
		velocity.y = speed * -1
	elif Input.is_action_pressed("ui_down"):
		velocity.y = speed
	else:
		velocity = Vector2.ZERO

	if velocity != Vector2.ZERO:
		_last_direction = velocity

	# play appropriate animation
	if velocity.x > 0:
		_animated_sprite.play("Run_left")
	elif velocity.x < 0:
		_animated_sprite.play("Run_right")
	elif velocity.y > 0:
		_animated_sprite.play("Run_down")
	elif velocity.y < 0:
		_animated_sprite.play("Run_up")
	else:
		# velocity is zero, so play idle animation based on last direction
		play_idle_animation()

func play_idle_animation():
	if _last_direction.x > 0:
		_animated_sprite.play("Idle_right")
	if _last_direction.x < 0:
		_animated_sprite.play("Idle_left")
	if _last_direction.y > 0:
		_animated_sprite.play("Idle_down")
	if _last_direction.y < 0:
		_animated_sprite.play("Idle_up")

As a side note, you only need 1 animation per axis. I.e., just horizontally or vertically flip _animated_sprite by setting it’s x or y scale property to -1 or 1. But that’s a different exercise…

Good luck, have fun

PS: Could you combine the two sets of IF statements in _process? Yes. But there’s a core design principle in programming of separating concerns, so the first concern is figuring out velocity, the next concern is figuring out what animation to play. Adhering to this principle makes code easier to maintain and leads to less bugs. For example, technically, you shouldn’t be asking animation sprite to play the animation on every frame if it’s already playing the correct animation. Godot is made to be simple, so it ignores this “mistake” by checking internally if the requested animation is already playing and continues to play the animation instead of restarting it. But in many other instances you’ll have to rely on your own checks like that. By separating code based on concerns, you can do those kinds of checks separately from other concerns, which keeps code cleaner and easier to read and maintain. So it’s a good thing to practice always.

4 Likes

Man thank you. I’ve been fighting with my code for months now. My only reference for learning is watching youtube videos and reading the documentation. I just think that sometimes the documentation is not that clear. I love the Godot engine.

I trying to learn the more engineering aspects of the engine. Like you said its the more design principals of programming. I’m attracted to that. I’m trying to use more autoload in my code.

Anyway thanks again. You’ll hear more about me.

You’re welcome, glad it helps.

YT tutorials and docs are good (here’s a great tutorial I link to everyone if you haven’t done it yet: https://www.youtube.com/watch?v=nAh_Kx5Zh5Q), but if you have a long-term attitude about this, nothing will beat just learning programming in general, not as related to Godot. And for that - either complete courses or books, ideally both. They guide you through the fundamentals in a coherent way that makes you understand how underlying software and languages work, which then helps you absorb tutorials and docs way, way faster.

Just google and pick anything in Python highly rated for the level you feel you are at.

Good luck!

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.