character stuck in air during jump

Godot Version

4.4.1

Question

when i press jump my character gets stuck floating in the air. if anyone can help id appriciate it im going nuts and chat gpt just scrambled my code to trash.

extends CharacterBody3D
var current_states = player_states.MOVE
enum player_states {MOVE, JUMP, SWORD, FALLING}

@export var speed := 4.0
@export var gravity := 4.0
@export var jump_force := 7.0

@onready var player_body = $CharacterArmature
@onready var anim = $AnimationPlayer
@onready var camera = $"../cam_gimbal"
@onready var  sword_collider = $CharacterArmature/Skeleton3D/Weapon_Cutlass/Weapon_Cutlass/sword/sword_collider
@onready var anim_tree = $AnimationTree
@onready var anim_state =  anim_tree.get("parameters/playback")

var angular_speed = 10

var movement
var direction
var sprint_speed = 10.0


func _physics_process(delta):
	match current_states:
		player_states.MOVE:
			move(delta)
		player_states.JUMP:
			jump()
		player_states.SWORD:
			sword(delta)
		player_states.FALLING:
			falling(delta)
			
func anim_set():
	anim_tree.set("parameters/air_state/start_jump/blend_position", movement)
	anim_tree.set("parameters/attack_state/Sword/blend_position",movement)
	anim_tree.set("parameters/ground_state/Idle/blend_position", movement)
	anim_tree.set("parameters/ground_state/walk/blend_position", movement)
	anim_tree.set("parameters/ground_state/running/blend_position", movement)
	anim_tree.set("parameters/damage_state/hurt/blend_position", movement)
	
func _input(_event):
	if Input.is_action_just_pressed("ui_sword"):
		current_states = player_states.SWORD
	if Input.is_action_just_pressed("ui_accept"):
		#current_states = player_states.JUMP
		jump()
		
func input_movement(delta):
	movement = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
	direction = Vector3(movement.x, 0, movement.y).rotated(Vector3.UP, camera.rotation.y).normalized()
		
	if direction:
		velocity.x = direction.x * speed
		velocity.z = direction.z * speed
		player_body.rotation.y = lerp_angle(player_body.rotation.y, atan2(velocity.x, velocity.z), delta * angular_speed)
	else:
		velocity.x = move_toward(velocity.x, 0, speed)
		velocity.z = move_toward(velocity.z, 0, speed)
	move_and_slide()
		
func move(delta):
	anim_tree["parameters/ground_state/conditions/standing"] = true
	movement = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
	#direction = (transform.basis * Vector3(movement.x, 0, movement.y)).normalized()
	direction = Vector3(movement.x, 0, movement.y).rotated(Vector3.UP, camera.rotation.y).normalized()
	var sprint = false
	
	if Input.is_action_pressed("ui_sprint"):
		sprint = true
	if Input.is_action_just_released("ui_sprint"):
		sprint = false
	
	if direction && sprint == false:
		anim_set()
		anim_tree["parameters/ground_state/conditions/moving"] = true
		anim_state.travel("ground_state/Walk")
		#anim.play("Walk")
		velocity.x = direction.x * speed
		velocity.z = direction.z * speed
		player_body.rotation.y = lerp_angle(player_body.rotation.y, atan2(velocity.x, velocity.z), delta * angular_speed)
	elif direction && sprint == true:
		#anim.play("Run")
		anim_tree["parameters/ground_state/conditions/running"] = true
		anim_state.travel("ground_state/Running")
		velocity.x = direction.x * sprint_speed
		velocity.z = direction.z * sprint_speed
		player_body.rotation.y = lerp_angle(player_body.rotation.y, atan2(velocity.x, velocity.z), delta * angular_speed)
	else:
		sword_collider.disabled = true
		#anim.play("Idle")
		anim_tree["parameters/ground_state/conditions/standing"] = true
		anim_state.travel("ground_state/Idle")
		
		velocity.x = move_toward(velocity.x, 0, speed)
		velocity.z = move_toward(velocity.z, 0, speed)
		
	velocity.y -= gravity * delta
	move_and_slide()
	
func jump():
		velocity.y = jump_force
		anim_tree["parameters/conditions/jumping"] = true
		anim_state.travel("air_state/start_jump")
		
		if velocity.y > 5.0:
			current_states = player_states.FALLING
		#anim.play("Jump")
		#await anim.animation_finished
		#reset_states()
		move_and_slide()

func falling(delta):
	var new_gravity = gravity * 2 
	velocity.y = new_gravity * delta
	input_movement(delta)
	
	if is_on_floor():
		anim_tree["parameters/conditions/on_ground"] = true
		anim_state.travel("landing")
		
	move_and_slide()
	
func sword(delta):
	input_movement(delta)
	anim_state.travel("attack_state/Sword")
	#anim.play("Sword")
	#await anim.animation_finished
	reset_states()
	
func reset_states():
	current_states = player_states.MOVE
1 Like

i fixed so far by adding in the new gravity func * 2 and also replaced the - in the line after that chat gpt decided to take out

func falling(delta):
	var new_gravity = gravity * 2
	velocity.y -= new_gravity * delta
	input_movement(delta)

I’d advise against using “ai” for a variety of reasons, particularly with Godot.

When you post here, if you put your code inside backticks:

```gdscript
code here
```

It formats nicely:

extends CharacterBody3D
var current_states = player_states.MOVE
enum player_states {MOVE, JUMP, SWORD, FALLING}

@export var speed := 4.0
@export var gravity := 4.0
@export var jump_force := 7.0

@onready var player_body = $CharacterArmature
@onready var anim = $AnimationPlayer
@onready var camera = $“../cam_gimbal”
@onready var sword_collider = $CharacterArmature/Skeleton3D/Weapon_Cutlass/Weapon_Cutlass/sword/sword_collider
@onready var anim_tree = $AnimationTree
@onready var anim_state = anim_tree.get(“parameters/playback”)

var angular_speed = 10

var movement
var direction
var sprint_speed = 10.0

func _physics_process(delta):
    match current_states:
        player_states.MOVE:
            move(delta)
        player_states.JUMP:
            jump()
        player_states.SWORD:
            sword(delta)
        player_states.FALLING:
            falling(delta)

func anim_set():
    anim_tree.set(“parameters/air_state/start_jump/blend_position”, movement)
    anim_tree.set(“parameters/attack_state/Sword/blend_position”,movement)
    anim_tree.set(“parameters/ground_state/Idle/blend_position”, movement)
    anim_tree.set(“parameters/ground_state/walk/blend_position”, movement)
    anim_tree.set(“parameters/ground_state/running/blend_position”, movement)
    anim_tree.set(“parameters/damage_state/hurt/blend_position”, movement)

func _input(_event):
    if Input.is_action_just_pressed(“ui_sword”):
        current_states = player_states.SWORD
    if Input.is_action_just_pressed(“ui_accept”):
        #current_states = player_states.JUMP
        jump()

func input_movement(delta):
    movement = Input.get_vector(“ui_left”, “ui_right”, “ui_up”, “ui_down”)
    direction = Vector3(movement.x, 0, movement.y).rotated(Vector3.UP,  camera.rotation.y).normalized()

    if direction:
        velocity.x = direction.x * speed
        velocity.z = direction.z * speed
        player_body.rotation.y = lerp_angle(player_body.rotation.y, atan2(velocity.x, velocity.z), delta * angular_speed)
    else:
        velocity.x = move_toward(velocity.x, 0, speed)
        velocity.z = move_toward(velocity.z, 0, speed)
    move_and_slide()

func move(delta):
    anim_tree[“parameters/ground_state/conditions/standing”] = true
    movement = Input.get_vector(“ui_left”, “ui_right”, “ui_up”, “ui_down”)
    #direction = (transform.basis * Vector3(movement.x, 0, movement.y)).normalized()
    direction = Vector3(movement.x, 0, movement.y).rotated(Vector3.UP, camera.rotation.y).normalized()
    var sprint = false

    if Input.is_action_pressed("ui_sprint"):
        sprint = true
    if Input.is_action_just_released("ui_sprint"):
        sprint = false

    if direction && sprint == false:
        anim_set()
        anim_tree["parameters/ground_state/conditions/moving"] = true
        anim_state.travel("ground_state/Walk")
        #anim.play("Walk")
        velocity.x = direction.x * speed
        velocity.z = direction.z * speed
        player_body.rotation.y = lerp_angle(player_body.rotation.y, atan2(velocity.x, velocity.z), delta * angular_speed)
    elif direction && sprint == true:
        #anim.play("Run")
        anim_tree["parameters/ground_state/conditions/running"] = true
        anim_state.travel("ground_state/Running")
        velocity.x = direction.x * sprint_speed
        velocity.z = direction.z * sprint_speed
        player_body.rotation.y = lerp_angle(player_body.rotation.y, atan2(velocity.x, velocity.z), delta * angular_speed)
    else:
        sword_collider.disabled = true
        #anim.play("Idle")
        anim_tree["parameters/ground_state/conditions/standing"] = true
        anim_state.travel("ground_state/Idle")
	
        velocity.x = move_toward(velocity.x, 0, speed)
        velocity.z = move_toward(velocity.z, 0, speed)
	
    velocity.y -= gravity * delta
    move_and_slide()

func jump():
    velocity.y = jump_force
    anim_tree[“parameters/conditions/jumping”] = true
    anim_state.travel(“air_state/start_jump”)

    if velocity.y > 5.0:
        current_states = player_states.FALLING
	#anim.play("Jump")
	#await anim.animation_finished
	#reset_states()
	move_and_slide()

func falling(delta):
    var new_gravity = gravity * 2
    velocity.y = new_gravity * delta
    input_movement(delta)

if is_on_floor():
	anim_tree["parameters/conditions/on_ground"] = true
	anim_state.travel("landing")
	
move_and_slide()
    func sword(delta):
    input_movement(delta)
    anim_state.travel(“attack_state/Sword”)
    #anim.play(“Sword”)
    #await anim.animation_finished
    reset_states()

func reset_states():
    current_states = player_states.MOVE
1 Like

Looking at this, if the player presses the ui_accept button, it calls jump(). That sets an upwards velocity, kicks the jump animation, and does a frame of movement with the move_and_slide(). That’s fine as far as it goes, but then nothing knows that the character is jumping, and in subsequent frames nothing is going to clean up after.

Offhand, I don’t see any way that the jump ever ends. There’s no end of animation check, no on the ground check, and the only code that puts the character in FALLING mode will only be called right at the beginning of the jump where it won’t do anything.

https://youtu.be/TkIZ3InT4eM?si=8NVm7Ac2dnPaD7yv this is the tutorial im following. in it he says its not the best way but it works which so far has been right. he didnt have me do any of the resets or checks through code but put the resets in the animation player, also why i posted here was to get some feed back on how to make it better also, ya ai i decided to leave out and ask real humans for advice

You need to do something to handle the jump over successive frames. You’re kind of doing that, but your jump() function is trying to do too much. What you want is probably something more like:

func jump():
    # trigger a new jump
    velocity.y -= JUMP_FORCE
    anim_tree.do_jump_stuff()

func update_jump():
    # call this each frame when jumping...
    if velocity.y > 5.0:
        current_state = state.FALLING
    # maybe check the case where we jumped up to a platform and are on the floor here...
    move_and_slide()