What's wrong with my double jump?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Henry Liu

Originally posted to discord:
Could someone give me some insight as to what might be causing this bug:
I’m trying to implement a double jump for my character. If he’s on the ground and he jumps then he gets another one, if he walks off a ledge or the ground disappears beneath he still has one. Basically, he has one midair jump that resets when he touches the ground.

Problem: occasionally (it seems to be randomly) when i jump from the ground my midair jump disappears and i cannot jump. Also seems to only happen when moving left or right while jumping.

So my logic is: keep track of the number of midair jumps you have left (it’s 1 for this case). if you’re currently grounded and you press jump, ur character jumps but no values change. If you press jump and you’re not grounded and you have more than 0 midair jumps left, it subtracts 1 from the midair jumps, and ur character jumps. Otherwise, you’re character doesn’t jump and no values get updated. On each update of _physics_process() i check whether or not you’re grounded at the very start, and store it in a variable and then use that for everything else. Then i check for jump input, and then i check for horizontal movement inputs. move_and_slide() is the final line of _physics_process() if that makes any difference. Im guessing it has something to do with how is_on_floor() only updates when move_and_slide() gets called? I have no idea though and ive been stuck for a few hours.

extends KinematicBody2D
export var xSpeed = 500;
export var gravity = 1000;
export var jumpSpeed = 600;

var motion = Vector2(0,0);
const UP = Vector2(0,-1);
var midairJumpsLeft = 1;
var grounded = true;

func _physics_process(delta): #Update -------------

	applyGravity(delta);
	checkJump();
	horizontalMove();
	
func _process(delta): 
	print(midairJumpsLeft);
#-----------------------------------

func applyGravity(delta):
	if (is_on_floor()):
		grounded = true;
		midairJumpsLeft = 1; #also reset jumps when grounded
		motion.y = 0;
	else: 
		grounded = false;
		motion.y += gravity*delta;

func checkJump():
	if (Input.is_action_just_pressed("player_jump")):
		if (not grounded) && midairJumpsLeft > 0:
			midairJumpsLeft = 0;
			motion.y = -jumpSpeed;
		elif grounded:
			midairJumpsLeft = 1;
			motion.y = -jumpSpeed;

func horizontalMove():
	motion.x = 0;
	if (Input.is_action_pressed("player_left")):
		motion.x += -xSpeed;
	if (Input.is_action_pressed("player_right")):
		motion.x += xSpeed;
	move_and_slide(motion, UP);

Also I apologize for the unnecessary semicolons and parentheses, it’s just what im used to at this point.

#EDIT: Link to video of bug

:bust_in_silhouette: Reply From: Dlean Jeans

Try calling horizontal_move() before applyGravity(). is_on_floor() is only updated after move_and_slide() is called.

I’d already tried that. It doesn’t work.

I did actually find a reddit comment from a year ago which solved all my issues.
First of all the perpetrator is

if is_on_floor():
    velocity.y = 0

This causes the weird interaction where grounded rapidly switches between true and false.

However, removing this statement will make it so that you continue to generate speed from gravity even as you stand on solid ground. To solve this, instead of just calling move_and_slide(), I needed to set velocity = move_and_slide() which did all the calculations for me.

Henry Liu | 2019-07-02 19:55

:bust_in_silhouette: Reply From: Henry Liu

I did actually find a reddit comment from a year ago which solved all my issues.
First of all the perpetrator is

if is_on_floor():
    velocity.y = 0

This causes the weird interaction where grounded rapidly switches between true and false.

However, removing this statement will make it so that you continue to generate speed from gravity even as you stand on solid ground. To solve this, instead of just calling move_and_slide(), I needed to set velocity = move_and_slide() which did all the calculations for me.