Jump caused by jump_buffer_timer is not a variable jump.

Godot Version

Godot 4.6 Beta-2 (32-bit)

Question

Jump caused by jump_buffer_timer is not a variable jump.

Hello! I hope that you are doing well!

I am pretty new to Godot and game dev, so correct my silly mistakes (if any, of course).

I have created a 2D platformer from a video of brackeys (How to make a game), I added a nice amount of things, two of them were jump buffering and variable jump.

As the question says, whenever I jump normally, when on the floor, it’s a variable jump, but when the jump is triggered by the jump buffer, it’s a full jump, which I don’t want.

player.gd (I think only the physics_process function is important):

extends CharacterBody2D
class_name Player
signal health_changed
signal hit
signal died

const SPEED: float = 130.0
const JUMP_VELOCITY: float = -300.0
const JUMP_BUFFER_TIME: float = 0.12
const MAX_HEALTH: int = 3
@export var health: int = 3:
	set(desired_value):
		health = clamp(desired_value, 0, MAX_HEALTH)
		health_changed.emit()
var direction: float
var jump_available: bool = true
var jump_requested: bool = false
var knockback: Vector2 = Vector2.ZERO # Direction and speed of knockback.
var knockback_timer: float = 0.0
var _jump_buffer_timer: float = 0.0
#region @onready var
@onready var state_machine: Node = $StateMachine
@onready var collision_shape_2d: CollisionShape2D = $CollisionShape2D
@onready var death_timer: Timer = $Timers/DeathTimer
@onready var hit_timer: Timer = $Timers/HitTimer
@onready var _animated_sprite_2d: AnimatedSprite2D = $AnimatedSprite2D
@onready var _jump_sound: AudioStreamPlayer = $Sounds/JumpSound
@onready var _hurt_sound: AudioStreamPlayer = $Sounds/HurtSound
@onready var _coyote_timer: Timer = $Timers/CoyoteTimer
#endregion

func _ready() -> void: # Testing purposes ONLY.
	Engine.time_scale = 0.4

func _physics_process(delta: float) -> void:
#region if dead or hit
	# Avoid running movement when player is dead.
	if state_machine.current_state is PlayerDeath:
		if not is_on_floor():
			velocity += get_gravity() * delta

		move_and_slide()
		return

	elif state_machine.current_state is PlayerHit:
		if not is_on_floor():
			velocity += get_gravity() * delta

		if knockback_timer > 0.0: # Turn on knockback and tick down timer.
			velocity = knockback
			knockback_timer -= delta
			if knockback_timer <= 0.0: # Turn off knock back.
				knockback = Vector2.ZERO

		if _jump_buffer_timer > 0.0:
			_jump_buffer_timer = 0.0

		move_and_slide()
		return
#endregion

	# Implement jump_buffer.
	if _jump_buffer_timer > 0.0:
		_jump_buffer_timer -= delta # Reduce by delta if _jump_buffer_timer > 0.0.
	else:
		jump_requested = false

	# Add the gravity.
	if not is_on_floor():
		velocity += get_gravity() * delta
		if _coyote_timer.is_stopped():
			_coyote_timer.start()
	else: # Do when on floor.
		if not jump_available:
			_coyote_timer.stop()
			jump_available = true

	# Handle jump.
	if jump_available and jump_requested and _jump_buffer_timer > 0.0:
		velocity.y = JUMP_VELOCITY
		_jump_buffer_timer = 0.0

	elif velocity.y < 0.0:
		if Input.is_action_just_released("jump"):
			velocity.y *= 0.5

	# Find direction: -1, 0, 1
	direction = Input.get_axis("move_left", "move_right")

	# Flip the AnimatedSprite2D horizontally accordingly.
	if direction > 0:
		_animated_sprite_2d.flip_h = false
	elif direction < 0:
		_animated_sprite_2d.flip_h = true

	# Apply movement logic.
	if direction:
		velocity.x = direction * SPEED
	else:
		velocity.x = move_toward(velocity.x, 0, SPEED)

	move_and_slide()

func _input(event: InputEvent) -> void:
	if event.is_action_pressed("jump"):
		jump_requested = true
		_jump_buffer_timer = JUMP_BUFFER_TIME

func _on_coyote_timer_timeout() -> void:
	jump_available = false

func _on_death_timer_timeout() -> void:
	Engine.time_scale = 1.0
	get_tree().reload_current_scene()

func apply_knockback(knockback_direction: Vector2, force: float, knockback_duration: float) -> void:
	knockback = knockback_direction * force
	knockback_timer = knockback_duration

func hurt() -> void:
	health -= 1
	if health == 0:
		die()
		return
	hit.emit()

func die() -> void:
		died.emit()

func play_animation(animation_name: String) -> void:
	_animated_sprite_2d.play(animation_name.to_lower())

func play_sound(sound_name: String) -> void:
	match sound_name.to_lower():
		"jump":
			_jump_sound.play()
		"hurt":
			_hurt_sound.play()
		_:
			print("WARNING: Sound named '" + sound_name + "' not found.")

player_idle.gd:

extends State
class_name PlayerIdle
var player: Player

func physics_update(_delta: float) -> void:
	if player.jump_available and player.jump_requested:
		Transitioned.emit(self, "Jump")
		return

	if player.is_on_floor():
		if player.direction == 0:
			player.play_animation("idle")
		else:
			player.play_animation("run")

Thanks a lot for your precious time!

LL