GDScript double jump mechanic issue

Godot Version

4.1.1

GDScript double jump mechanic issue

Good afternoon!

Forgive me for my first post being a request for help, but I’m losing my mind rn.

I was working on a test player scene, specifically trying to implement a double jump mechanic. It works! But, it stops working if I change some things that are not visibly related.

Here is the working code:

extends CharacterBody2D

@export var SPEED = 200
@export var GRAVITY = 500
@export var JUMP_FORCE = 200

@onready var player_sprite = $AnimatedSprite2D

var direction = 0
var jumps_available = 2

func _process(delta):
	
	direction = Input.get_axis('left', 'right')
	
	animation_updater()
	
func _physics_process(delta):
	velocity.x = direction * SPEED
	if !is_on_floor():
		velocity.y += GRAVITY * delta
	
	if is_on_floor():
		jumps_available = 2
		
	if Input.is_action_just_pressed('jump') && jumps_available > 0:
		jumps_available -= 1
		velocity.y = -JUMP_FORCE
		
	move_and_slide()
	
func animation_updater():
	if direction != 0:  # Flip Sprite and keep last flip	
		player_sprite.flip_h = (direction < 0)
		
	if velocity == Vector2.ZERO:
		player_sprite.play('idle')
	else:  # Otherwise check what kind of movement
		if is_on_floor():
			player_sprite.play('running')
		else:  # Going up or down?
			if velocity.y > 0:
				player_sprite.play('falling')
			else:
				player_sprite.play('jumping')
				if jumps_available == 0:  # Play hop on second jump
					player_sprite.play('air_hop')
	

The issue is specifically within the _physics_process function. If I change the order of the if statement checking if the player is on the floor with the if statement checking for a jump input, it will allow me 1 extra jump… I’ve tested the value of jumps_available and for only 1 frame it will update but go straight back to the original value. Basically this version of the code doesn’t work and I don’t understand why:

func _physics_process(delta):
	velocity.x = direction * SPEED
	if !is_on_floor():
		velocity.y += GRAVITY * delta
		
	if Input.is_action_just_pressed('jump') && jumps_available > 0:
		jumps_available -= 1
		velocity.y = -JUMP_FORCE
		
	if is_on_floor():
		jumps_available = 2
		
	move_and_slide()

(Only quoted the part that’s different)

I don’t insist in having it this way, I only found out about this problem when I tried to put the jump and is_on_floor if’s within the _process function. I thought it would be better practice that way…

Is this a godot bug? Or am I missing something here?

Thanks for your time!

In this version of the code, let’s assume the player has pressed the “jump” input, and is currently on the floor with 2 jumps_available.

First you’re checking the jump input, so you subtract 1 from jumps_available and then set the velocity.

Now the player has 1 jumps_available.

Then, because the player is on the floor, you reset jumps_available to 2.

Afterwards, the player will be jumping into the air, but still have 2 jumps_available.

The confusion may be due to expecting that when you set velocity.y for the jump, it might immediately set the on_floor flag to false.
But, it does not. The character body does not actually leave the floor until the next time move_and_slide() is called.

The character body does not actually leave the floor until the next time move_and_slide() is called.

Here it is! This is what was missing in my head!! lol

I was not aware of that, thank you so much for the explanation. I was going a little coocoo!

1 Like

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