How to make a double jump script for your game

If you're wondering how to make a double jump script, you've probably realized that giving your player a little extra air time is the easiest way to make movement feel way more fun. There's something deeply satisfying about that second mid-air hop—it makes the controls feel responsive and gives the player a bit of a safety net if they mistime a gap. Whether you're working on a 2D platformer or a 3D adventure, the logic behind a double jump is pretty much the same across the board, even if the specific code looks a bit different depending on your engine.

In this breakdown, we're going to look at the core logic you need, some actual code examples for popular engines like Unity and Roblox, and—most importantly—how to make it feel "snappy" rather than floaty or broken.

The basic logic behind the jump

Before we start typing out lines of code, let's talk about what's actually happening under the hood. To get a double jump working, your script needs to keep track of a few specific things. If you just tell the game "jump whenever I press space," your player is going to fly off into the stratosphere like a rocket ship.

First, the script needs to know if the player is currently on the ground. This is usually handled by a boolean (a true/false check) often called isGrounded. When you're on the floor, your jump counter resets. When you press the jump button the first time, you launch upward, and the script records that you've used one jump.

The "magic" happens when the player presses the button again while isGrounded is false. The script checks: "Have I used my second jump yet?" If the answer is no, it applies another burst of vertical velocity. It then marks the second jump as "used" so the player can't just keep jumping forever. It sounds simple, but getting the timing right is where the real work happens.

How to make a double jump script in Unity (C#)

Unity is probably the most common place people want to implement this. Since Unity uses C#, we can write a clean little script that attaches to your character. You'll typically be using a Rigidbody2D (for 2D games) or a CharacterController (for 3D). Let's stick with 2D for this example since it's the most common use case for double jumping.

```csharp using UnityEngine;

public class PlayerMovement : MonoBehaviour { public float jumpForce = 10f; private Rigidbody2D rb; private int jumpCount = 0; public int maxJumps = 2; public bool isGrounded; public Transform groundCheck; public float checkRadius; public LayerMask whatIsGround;

void Start() { rb = GetComponent<Rigidbody2D>(); } void Update() { // Checking if we are touching the floor isGrounded = Physics2D.OverlapCircle(groundCheck.position, checkRadius, whatIsGround); // Reset the jump count when we land if (isGrounded) { jumpCount = 0; } // The actual jump logic if (Input.GetKeyDown(KeyCode.Space)) { if (isGrounded || jumpCount < maxJumps - 1) { rb.velocity = Vector2.up * jumpForce; jumpCount++; } } } 

} ```

In this setup, we're using a jumpCount integer. We tell the game that as long as our jumpCount is less than our maxJumps, we're allowed to add velocity again. Notice that I used Input.GetKeyDown. This is super important. If you use GetKey, the game will register a jump for every single frame you hold the button down, and your character will zoom off the screen.

Doing it in Roblox (Luau)

Roblox works a bit differently because it has a built-in "Humanoid" system that handles a lot of the physics for you. However, the default Roblox character only jumps once. To learn how to make a double jump script in Roblox, you have to hook into the StateChanged event of the Humanoid.

You'd generally put this in a LocalScript inside StarterCharacterScripts:

```lua local UIS = game:GetService("UserInputService") local player = game.Players.LocalPlayer local character = player.Character or player.CharacterAdded:Wait() local humanoid = character:WaitForChild("Humanoid")

local canDoubleJump = false local hasDoubleJumped = false local oldPower = humanoid.JumpPower

function onJumpRequest() if not character or not humanoid or not character:IsDescendantOf(workspace) then return end if humanoid:GetState() == Enum.HumanoidStateType.Dead then return end

if canDoubleJump and not hasDoubleJumped then hasDoubleJumped = true humanoid.JumpPower = oldPower * 1.5 -- Give the second jump a little extra oomph humanoid:ChangeState(Enum.HumanoidStateType.Jumping) end 

end

humanoid.StateChanged:Connect(function(old, new) if new == Enum.HumanoidStateType.Landed then canDoubleJump = false hasDoubleJumped = false humanoid.JumpPower = oldPower elseif new == Enum.HumanoidStateType.Freefall then wait(0.1) -- Small delay so you don't double jump instantly canDoubleJump = true end end)

UIS.JumpRequest:Connect(onJumpRequest) ```

The logic here is a bit more "event-driven." We listen for when the player enters "Freefall" (meaning they've left the ground) and then enable the ability to double jump after a tiny fraction of a second. When they land, we reset everything.

Making it feel good: The "Juice"

One mistake a lot of beginners make is just slapping the code in and calling it a day. If you do that, the movement might feel "robotic." Here are a few ways to spice up your double jump script:

1. The Jump Buffer

Have you ever played a game where you pressed the jump button just a millisecond before you hit the ground, and the character did nothing? It feels terrible. A jump buffer saves that input for a few frames and executes the jump the moment the player touches the floor.

2. Coyote Time

Named after Wile E. Coyote, this is a grace period that lets the player jump even if they've already walked off the edge of a platform. Without this, players will feel like the game "ate" their jump. For a double jump script, you want to make sure the first jump (the Coyote jump) counts as the "grounded" jump, so they still have their mid-air hop available.

3. Gravity Scaling

Usually, jumping feels better if you fall faster than you rise. In Unity, you can easily tweak this by checking if the player's vertical velocity is negative (falling) and then increasing the gravityScale on the Rigidbody. This makes the jump feel snappy and less floaty.

4. Visual Feedback

A double jump shouldn't just be a change in velocity. Add a little puff of smoke, a "flip" animation, or a slight screen shake. Even a simple sound effect makes the action feel like it has weight. If the player doesn't see something happen, the second jump can feel like a glitch rather than a feature.

Common pitfalls to avoid

While you're figuring out how to make a double jump script, you're probably going to run into a few bugs. Here are the ones I see most often:

  • The Infinite Jump: If you forget to increment your jumpCount or if your ground check is too sensitive, the player might be able to jump infinitely. Always check your "grounded" logic first. If your ground check radius is too big, the game might think you're "grounded" even when you're just near a wall.
  • The "Launch" Bug: If you add velocity instead of setting velocity, the second jump might combine with the momentum of the first jump and launch the player way higher than intended. It's usually better to set the velocity directly (e.g., rb.velocity = new Vector2(rb.velocity.x, jumpForce)) so the height is consistent.
  • Animation Clipping: If you trigger a "Jump" animation on every press, make sure the transitions in your animator (if using Unity) are set to "Can Transition To Self" or use a Trigger that resets correctly. Otherwise, the animation might get stuck on the first frame.

Wrapping things up

Learning how to make a double jump script is a bit of a rite of passage for game devs. It's one of those features that seems tiny but completely changes the flow of a level. The most important thing is to keep testing it. Play your game, jump around, and see if it feels right. Is the second jump too high? Is it too hard to time?

Don't be afraid to tweak the variables. Maybe your game feels better with a triple jump, or maybe the second jump should only be half as strong as the first. The code gives you the structure, but the "feel" comes from the tiny adjustments you make after the script is running. Happy coding!