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
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
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
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).
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()