Why are my falling and jumping animations not playing?

first time writing.

here is my script:

extends CharacterBody2D

const SPEED = 200
const JUMP_VELOCITY = -400
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")

func _physics_process(delta):
	if not is_on_floor():
		velocity.y += gravity * delta
		$AnimatedSprite2D.play("falling")

	if Input.is_action_just_pressed("ui_accept") and is_on_floor():
		velocity.y = JUMP_VELOCITY
		$AnimatedSprite2D.play("jumping")
		
	var direction = Input.get_axis("left", "right")
	if direction:
		velocity.x = direction * SPEED
		$AnimatedSprite2D.play("running")
		if velocity.x < 0:
			$AnimatedSprite2D.flip_h = true
		else:
			$AnimatedSprite2D.flip_h = false
	else:
		velocity.x = move_toward(velocity.x, 0, 15)
		$AnimatedSprite2D.play("idle")

	move_and_slide()

How exactly did you configure the animations? docs


you could first insert print -output everywhere before each play function and check whether the if-conditions are executed at all.


example:

............
	if not is_on_floor():
		velocity.y += gravity * delta
		print("falling")
		$AnimatedSprite2D.play("falling")
............

Bildschirmfoto 2023-12-26 um 23.39.20

Your earlier animations are being overwritten by your later animations. The only animations that will play at the end are “running” and “idle” since they are at the end. To fix this, use more else blocks.

1 Like

As @shatteredreality said, you need to add an else statement, like so:

func _physics_process(delta):
	if not is_on_floor():
		velocity.y += gravity * delta
		$AnimatedSprite2D.play("falling")
	else:
		var jumping := false
		if Input.is_action_just_pressed("ui_accept") and is_on_floor():
			velocity.y = JUMP_VELOCITY
			$AnimatedSprite2D.play("jumping")
			jumping = true
		
		var direction = Input.get_axis("left", "right")
		if direction:
			velocity.x = direction * SPEED
			if not jumping:
				$AnimatedSprite2D.play("running")
			if velocity.x < 0:
				$AnimatedSprite2D.flip_h = true
			else:
				$AnimatedSprite2D.flip_h = false
		else:
			velocity.x = move_toward(velocity.x, 0, 15)
			if not jumping:
				$AnimatedSprite2D.play("idle")

	move_and_slide()

Note that the above solution still will cause the “jumping” animation to not play. You probably want to check if the jumping animation is playing before playing another animation.

ok I did get lazy, fixed now.

Hey thanks for the reply.

I did try this but only the falling animation seems to play even when I press “space” to jump. I don’t know why it does this but I will try to fix it and update it here if I find a solution.

_physics_process() will be called every frame. The next frame after you apply the initial jump impulse, not is_on_floor() will be true, so it will change to the fall animation.

I don’t use AnimatedSprite2D’s very often, but I believe calling play() restarts the animation from the beginning. I think this is probably why @shatteredreality recommended checking first to see if the desired animation is already playing before calling play() again. (Edit: incorrect, see following posts.)

I don’t know how you have your animations set up, but if you want the jump animation to play while the node is ascending, and the fall to play while it is descending, for example, you can do something like:

if not is_on_floor():
		velocity.y += gravity * delta
		if velocity.y <= 0:
			if not $AnimatedSprite2D.animation == "jumping":
				$AnimatedSprite2D.play("jumping")
		else:
			if not $AnimatedSprite2D.animation == "falling":
				$AnimatedSprite2D.play("falling")

You could also skip the jumping animation altogether in this part of the code, since it will already be started when the jump starts further down. But there may be edge cases this will catch as your code gets more complex.

This kind of code can get complicated quickly, so if it is getting disorganized, you might want to consider a simple state machine, like in ShaggyDev’s tutorial here: Starter state machines in Godot 4 – The Shaggy Dev Then you would only change the animation when the state is changed.

1 Like

No, play does not restart the animation from the beginning if the animation is the same as the one playing.

1 Like

Sorry, I misread your earlier answer.

Then the example I posted wouldn’t need the checks if they are meant to be looping animations. (AnimatedSprite2D.play() behavior change between Godot 3 and Godot 4 should be documented · Issue #8372 · godotengine/godot-docs · GitHub)