Kinematic Jump Formulas for 2D and 3D Games
2026/08/22
- Type
- Learning Resource
- Format
- Study Guide
- Version
- Godot 4.x
- Subject Tags
- Code
- MIT
- Game Assets
- CC BY-NC-SA
- All else
- 2016-2026, GDQuest© - All rights reserved
- Created
- Updated
- 2025/06/15
- 2026/08/22
Instead of tweaking jump speed and gravity values until they "feel right," you can use kinematic jump formulas to calculate the exact physics values you need. Just input design-friendly settings like how high you want your character to jump, how long it should take to reach the peak, and how far it should travel horizontally.
This approach gives you precise control over your character's jump height and how long they take. I'll show you a few simple functions you can copy and paste into any project and reuse for any jumping mechanic in your 2D and 3D games.
You can copy these formulas into any project to design jumps by their height, timing, and horizontal distance instead of guessing at physics values.
When you design jumps with speed and gravity, each property affects both height and timing. You end up tweaking both values repeatedly without knowing the exact jump height. It works, but it's not ideal.
With the kinematic jump formulas, you can input exact values like "I want my character to jump 50 pixels high and travel 100 pixels horizontally." The formulas calculate the exact speed and gravity values for you.
Also, knowing the exact height and length of jumps paves the way for more advanced systems like pathfinding with enemies that can jump over obstacles or chase the player across platforms.
Plus, it works the same in 2D and 3D games, so you can reuse these formulas in any project.
This formula calculates the upward velocity you need to reach a specific height in a specific time.
func calculate_jump_speed(height: float, time_to_peak: float) -> float:
return (-2.0 * height) / time_to_peakIt has two parameters:
height: How high the jump should reach. Use pixels in 2D and meters in 3Dtime_to_peak: How long it takes to reach maximum height in secondsUse it like this:
@export var jump_height := 50.0
@export var jump_time_to_peak := 0.4
@onready var jump_speed := calculate_jump_speed(jump_height, jump_time_to_peak)
func _physics_process(delta: float) -> void:
if Input.is_action_just_pressed("jump") and is_on_floor():
velocity.y = jump_speed_ready() function runs (or using @onready) ensures that the exported variables have the expected values set before you use them.This formula calculates the gravity you need to reach a specific height in a specific time.
func calculate_jump_gravity(height: float, time_to_peak: float) -> float:
return (2.0 * height) / pow(time_to_peak, 2.0)It has two parameters:
height: How high the jump should reach. Use pixels in 2D and meters in 3Dtime_to_peak: How long it takes to reach maximum height in secondsThis assumes you want an asymmetrical jump, where the character rises slower than they fall. This makes it easier for the player to control the jump height and landing (many games use this approach).
Use it like this:
@export var jump_height := 50.0
@export var jump_time_to_peak := 0.4
@onready var up_gravity := calculate_jump_gravity(jump_height, jump_time_to_peak)
func _physics_process(delta: float) -> void:
if velocity.y <= 0.0:
velocity.y += up_gravity * deltaIn many games, the jump has different gravity when going up vs. going down. This helps the player land precisely on platforms.
This formula is the same as for upward gravity, but it calculates gravity based on the time to return to ground level. I wrote a separate function for clarity, but feel free to reuse the calculate_jump_gravity() function if you prefer.
func calculate_fall_gravity(height: float, time_to_descent: float) -> float:
return (2.0 * height) / pow(time_to_descent, 2.0)The parameters and usage are the same as for the rising portion of the jump:
@export var jump_height := 50.0
@export var jump_time_to_descent := 0.25
@onready var fall_gravity := calculate_fall_gravity(jump_height, jump_time_to_descent)
func _physics_process(delta: float) -> void:
if velocity.y <= 0.0:
velocity.y += up_gravity * delta
else:
velocity.y += fall_gravity * deltaThis formula calculates the horizontal speed needed to travel a specific distance during the complete jump. This assumes the jump is asymmetrical, meaning the time to reach the maximum height is different from the time to fall back down.
func calculate_jump_horizontal_speed(distance: float, time_to_peak: float, time_to_descent: float) -> float:
return distance / (time_to_peak + time_to_descent)Use it like this:
@export var jump_distance := 100.0
@export var jump_time_to_peak := 0.4
@export var jump_time_to_descent := 0.25
@onready var horizontal_speed = calculate_jump_horizontal_speed(jump_distance, jump_time_to_peak, jump_time_to_descent)
func _physics_process(delta: float) -> void:
var input_direction := Input.get_action_strength("move_right") - Input.get_action_strength("move_left")
if Input.is_action_just_pressed("jump"):
velocity.x = sign(input_direction) * horizontal_speedIf your jump has the same time to rise and fall, you can simplify the formula to:
func calculate_jump_horizontal_speed(distance: float, time_to_ground: float) -> float:
return distance / time_to_groundThe kinematic jump formulas work in 2D and 3D, but the code examples in this guide are for 2D. In 2D, the y axis points down in Godot, while in 3D, the y axis points up. So, if you're working on a 3D game, you need to flip the vertical movement:
calculate_jump_speed() to return a positive valuecalculate_jump_gravity() and calculate_fall_gravity() to return a negative valueThe updated functions would look like this (I changed their name to indicate they're specific to 3D games):
func calculate_jump_speed_3d(height: float, time_to_peak: float) -> float:
return (2.0 * height) / time_to_peak
func calculate_jump_gravity_3d(height: float, time_to_peak: float) -> float:
return -(2.0 * height) / pow(time_to_peak, 2.0)
func calculate_fall_gravity_3d(height: float, time_to_descent: float) -> float:
return -(2.0 * height) / pow(time_to_descent, 2.0)If you copied the functions from this guide and used them without flipping the sign in a 3D game, your character would move upward indefinitely.
Alternatively, you could keep the same functions as in 2D but flip the sign in the character calculations. The code in _physics_process() would then look like this:
func _physics_process(delta: float) -> void:
if Input.is_action_just_pressed("jump") and is_on_floor():
velocity.y = -1.0 * jump_speed
if velocity.y > 0.0:
velocity.y -= up_gravity * delta
else:
velocity.y -= fall_gravity * deltaIn Module 13, Lesson 1 of Learn 2D Gamedev From Zero, you write a polished side-scroller character controller using a state machine and these jump formulas to get tight controls. In Module 6, Lesson 10 of Learn 3D Gamedev From Zero, you apply the same formulas to spawn rigidbody-based pickups from a chest up to an exact height using physics impulses.
Don't stop here. Step-by-step tutorials are fun but they only take you so far.
Try one of our proven study programs to become an independent Gamedev truly capable of realizing the games you’ve always wanted to make.
Get help from peers and pros on GDQuest's Discord server!
20,000 membersJoin ServerThere are multiple ways you can join our effort to create free and open source gamedev resources that are accessible to everyone!
Sponsor this library by learning gamedev with us onGDSchool
Learn MoreImprove and build on assets or suggest edits onGithub
Contributeshare this page and talk about GDQUest onRedditYoutubeTwitter…
Site in BETA!found a bug?