How to make jump hang time

Godot Version

<stable4.2>

Question

<Im trying to make jump mechanic feel good. id like to know how to add hang time or apex modifier to make player stay in air for short period of time without changing jump height.

@export var jump_time_to_peak: float = 0.45
@export var jump_height: float = 89
@onready var jump_velocity: float = (jump_height / jump_time_to_peak) * 2.0
@onready var jump_gravity: float = jump_velocity / jump_time_to_peak
@export var jump_time_to_descent: float = 0.35
@onready var descent_velocity: float = (jump_height / jump_time_to_descent) * 2.0
@onready var fall_gravity: float = descent_velocity / jump_time_to_descent

func get_gravity() -> float:
	return jump_gravity if velocity.y < 0.0 else fall_gravity
if Input.is_action_just_pressed("jump"):
		player.velocity.y -= player.jump_velocity
  1. Create two bool variables: is_jumping and is_hanging
  2. Create a Timer node and connect the timeout signal to your code
  3. In the code that handle the jump input, after apply the jump_velocity, set is_jumping to true
  4. Somewhere in your _physics_process callback, check if is_jumping == true and velocity.y >= 0, if is, set is_jumping to false, is_hanging to true, velocity.y to 0 and start the timer
  5. In your get_gravity function, check if is_hanging == true, if is, return 0
  6. In your timeout function, set is_hanging to false

I forgot to tell you, but I am using node based state machine. And I have no idea how to incorporate with fall state. If player is no on floor, state will transition to fall immediately. Thus, if is_jumping == true: player.velocity.y = 0 will not work. implementing hang time and coyote time while having fall state, jump state, and air jump state is giving me a headache. I would very much appreciate if you could give me a hand to solve this problem.

In this case i need to see the entire code to have a better idea or look the project

here is my player script

The jump hang and the coyote time has the same principle, you’ll delay the starting of an action, so both will do basicly the same thing in different moment

  1. In your player code create three variables: current_hanging_time, max_hanging_time and is_on_zero_gravity
  2. In the get_gravity function, check if is_on_zero_gravity == true and if is, return zero
  3. In the jump/airjump state code in the if player.velocity.y > 0 change to if player.velocity.y >= 0 after check if currrent_hanging_time > max_hanging_time, if is, change to fall state and is_on_zero_gravity = false, otherwise increase current_hanging_time += delta and is_on_zero_gravity = true
  4. In the enter function, make sure to zero current_hanging_time

The coyote time is the same thing, with the different you’ll create two different variables (current_coyote_time and max_coyote_time) and will use is_on_zero_gravity like the jump state:

  1. After create the variables, in the run state after the check if not player.is_on_floor() you’ll do the same thing, with the difference this time you’ll use the coyote variables
  2. Remember to zero the current_coyote_time in the enter function

Thank yo very much matheusmdx!
I was able to implement coyote time and variable jump by myself but I was still struggling to put hang time. I really appreciate your help. now player can stay in air. but how do you enable to airjump during hang time ?

if player.velocity.y >= 0.0: #If Player's velocity.y is larger than zero, FALL STATE
		if player.current_hang_time > player.max_hang_time:
			state_machine.transition_to("Fall")
			player.is_on_zero_gravity = false
		else:
			player.current_hang_time += delta
			player.is_on_zero_gravity = true
			if Input.is_action_just_pressed("jump") and player.air_jump==true:
				state_machine.transition_to("AirJump")
				player.air_jump = false
				player.is_on_zero_gravity = false

if Input.is_action_just_released("jump") and player.velocity.y < 0:
		player.velocity.y *= 0.7
		return

This enabled player to airjump during hang time, but now variable jump for airjump wont work…

never mind, i was forgetting to put if Input.is_action_just_released("jump") and player.velocity.y < 0: player.velocity.y *= 0.7 inside airjump script.

Now everything work. again, thank you very much