Jump animation not playing (3D)

Newbie here! I’m starting to learn godot and so far my character walks, runs and jumps, but the animation for jumping is not playing. I’ve made multiple tests but it doesn’t work. Here’s my script:

extends CharacterBody3D

@onready var animation_player: AnimationPlayer = $visuals/player/AnimationPlayer
@onready var visuals: Node3D = $visuals

var SPEED = 3.0
const JUMP_VELOCITY = 4.5

var walking_speed = 3.0
var running_speed = 5.0

var running = false
var walking = false

#Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity: float = ProjectSettings.get_setting("physics/3d/default_gravity")

	
func _physics_process(delta):
	
	if Input.is_action_pressed("run"):
		SPEED = running_speed
		running = true
	else:
		SPEED = walking_speed
		running = false
	# Add the gravity.
	if not is_on_floor():
		velocity.y -= gravity * delta

	# 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 input_dir := Input.get_vector("left", "right", "forward", "backward")
	var direction := (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
	if direction:
		if running:
			if animation_player.current_animation != "run":
				animation_player.play("Run")
		else:
			if animation_player.current_animation != "walk":
				animation_player.play("Walk")
		
		visuals.look_at(direction + position)

		velocity.x = direction.x * SPEED
		velocity.z = direction.z * SPEED
		
	else:
		if animation_player.current_animation != "Idle":
			animation_player.play("Idle")
			
		velocity.x = move_toward(velocity.x, 0, SPEED)
		velocity.z = move_toward(velocity.z, 0, SPEED)
		

	move_and_slide()

it might be a dumb mistake I made, but I just can’t seem to find a solution! If anyone might know what’s going on I’d love to hear you

you call animation_player.play on run walk and idle but not on jump, i think you should call it in the same block as where you set the velocity.y to jump velocity, and also make sure that you do not play idle run or walk animation when the jump animation is playing

I forgot to add that I did try writting this:

if Input.is_action_just_pressed("jump") and is_on_floor():
	velocity.y = JUMP_VELOCITY
	animation_player.play("Jump")

but it still doesn’t work, and when I tell it to not play any other animation while jumping, it doesn’t listen either (or perhaps I’m not writting down the script correctly)

I also tried this:

if Input.is_action_just_pressed("jump") and is_on_floor():
	velocity.y = JUMP_VELOCITY
	$visuals/player/AnimationPlayer.play("Jump")

and this:

if Input.is_action_just_pressed("jump") and is_on_floor():
	velocity.y = JUMP_VELOCITY
	animation_player.play("Jump")

elif Input.is_action_pressed("left"):
	animation_player.play("Walk")
	
elif Input.is_action_pressed("right"):
	animation_player.play("Walk")

elif Input.is_action_pressed("forward"):
	animation_player.play("Walk")
	
elif Input.is_action_pressed("backward"):
	animation_player.play("Walk")

else:
	if animation_player.is_playing():
		animation_player.play("Idle")

make sure that you do not play idle run or walk animation when the jump animation is playing otherwise it will only play for one frame

the if statement means that a new animation will play after the jump animation and overwrite it regardless of whether the jump animation is played or not

So what should I do?

You probably do not want to play walking animation while they are off the floor

if Input.is_action_just_pressed("jump") and is_on_floor():
	velocity.y = JUMP_VELOCITY
	animation_player.play("Jump")

# must walk on the floor and not be moving up
if is_on_floor() and velocity.y < 2:
	var walking = Input.get_vector("left", "right", "backward", "forward")
	if walking != Vector2.ZERO:
		animation_player.play("Walk")
	else:
		animation_player.play("Idle")

It looks like you are calling Jump before the run animation, so the animation is playing, but is getting changed instantly after by the run code. try making sure that run cannot be called while jumping.

if Input.is_action_just_pressed("jump") and is_on_floor():
	velocity.y = JUMP_VELOCITY

if is_on_floor():
     if direction:
		if running:
			if animation_player.current_animation != "run":
				animation_player.play("Run")
	    	else:
			if animation_player.current_animation != "walk":
				     animation_player.play("Walk")
else:
     animation_player.play("Jump")

you also may want to try shorting animation_player to something like “anim”. I find it a bit easier and faster

I tried your method, but now it overwrites the idle animation and only plays the jump animation when the character is not moving

Same here : (

Update: I tried some tweaking and I think I’m close to the the solution. This is the new code:

extends CharacterBody3D

@onready var animation_player: AnimationPlayer = $visuals/player/AnimationPlayer
@onready var visuals: Node3D = $visuals

var SPEED = 3.0
var JUMP_VELOCITY = 4.5

var walking_speed = 3.0
var running_speed = 7.0
var jumping_speed = 4.5

var running = false
var walking = false
var jumping = false

# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity: float = ProjectSettings.get_setting("physics/3d/default_gravity")

	
func _physics_process(delta):
	
	if Input.is_action_pressed("run"):
		SPEED = running_speed
		running = true
	else:
		SPEED = walking_speed
		running = false
	
	if Input.is_action_pressed("jump"):
		JUMP_VELOCITY = jumping_speed
		jumping = true
	else:
		JUMP_VELOCITY = jumping_speed
		jumping = false
	
	# Add the gravity.
	if not is_on_floor():
		velocity.y -= gravity * delta

	# Handle jump.
	if Input.is_action_pressed("jump"):
			velocity.y = JUMP_VELOCITY
			animation_player.play("Jump")

	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	var input_dir := Input.get_vector("left", "right", "forward", "backward")
	var direction := (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
	
	if direction and is_on_floor():
		if running:
			if animation_player.current_animation != "run":
				animation_player.play("Run")
		else:
			if animation_player.current_animation != "walk":
				animation_player.play("Walk")
		
		visuals.look_at(direction + position)

		velocity.x = direction.x * SPEED
		velocity.z = direction.z * SPEED
		
		else:
			animation_player.play("Idle")
			
		velocity.x = move_toward(velocity.x, 0, SPEED)
		velocity.z = move_toward(velocity.z, 0, SPEED)
		

	move_and_slide()

if I add a # like this:
else:
#animation_player.play(“Idle”)

it plays the jumping animation (yay!) but now the problem is that, of course, the idle animation is not playing, and the jumping animation just keeps going and going and going (to make matters worse, the other animations get very weird too).

What am I missing?

Ok I’m a dumass I finally fixed it. all the way to the bottom you’ll see that I wrote “if direction and is on floor” to tell it to play the jump anymation if it’s not on floor, but I forgot to add that to the “else” statement. Here’s the full script:

extends CharacterBody3D

@onready var animation_player: AnimationPlayer = $visuals/player/AnimationPlayer
@onready var visuals: Node3D = $visuals

var SPEED = 3.0
var JUMP_VELOCITY = 4.5

var walking_speed = 3.0
var running_speed = 7.0
var jumping_speed = 4.5

var running = false
var walking = false
var jumping = false

# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity: float = ProjectSettings.get_setting("physics/3d/default_gravity")

	
func _physics_process(delta):
	
	if Input.is_action_pressed("run"):
		SPEED = running_speed
		running = true
	else:
		SPEED = walking_speed
		running = false
	
	if Input.is_action_pressed("jump"):
		JUMP_VELOCITY = jumping_speed
		jumping = true
	else:
		JUMP_VELOCITY = jumping_speed
		jumping = false
	
	# Add the gravity.
	if not is_on_floor():
		velocity.y -= gravity * delta

	# Handle jump.
	if Input.is_action_pressed("jump"):
			velocity.y = JUMP_VELOCITY
			animation_player.play("Jump")

	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	var input_dir := Input.get_vector("left", "right", "forward", "backward")
	var direction := (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
	
	if direction and is_on_floor():
		if running:
			if animation_player.current_animation != "run":
				animation_player.play("Run")
		else:
			if animation_player.current_animation != "walk":
				animation_player.play("Walk")
		
		visuals.look_at(direction + position)

		velocity.x = direction.x * SPEED
		velocity.z = direction.z * SPEED
		
	else:
		if is_on_floor():
			animation_player.play("Idle")
			
		velocity.x = move_toward(velocity.x, 0, SPEED)
		velocity.z = move_toward(velocity.z, 0, SPEED)
		

	move_and_slide()

It worked BUT. I can’t jump forward or backward and anytime I press jump(space) in midair I just keep on jumping up repeatedly .