Menu
CoddyTech

Jumping

Part of the Building Real Games section of Coddy's Unity journey. Lesson 39 of 56.

A jump is a vertical speed set once, at the moment Space is pressed; the gravity the script already adds then slows the rise, stops it at the top and brings the controller back down. What remains is the start speed for a given height. Gravity takes speed away at a steady rate, so a jump that starts at speed v rises v * v / (2 * g) units before it stops. Turned around, the start speed for a height h is v = √(2 * g * h).

With gravity stored as a negative number, -20, and a jump 2.5 units high, that is Mathf.Sqrt(2.5f * -2f * -20f), the square root of 100: 10 units a second. The -2f turns the negative gravity positive, because the square root of a negative number is NaN:

if (controller.isGrounded && verticalSpeed < 0f)
{
    verticalSpeed = -2f;
}
if (Input.GetButtonDown("Jump") && controller.isGrounded)
{
    verticalSpeed = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
verticalSpeed += gravity * Time.deltaTime;

The reset tests verticalSpeed < 0f, so it only ends falls: a plain if (controller.isGrounded) reset after the jump line would overwrite the jump speed on the frame of the jump. The controller.isGrounded test on the jump stops jumps in mid-air. Change jumpHeight or gravity in the Inspector and the jump still reaches exactly jumpHeight, while a fixed speed such as verticalSpeed = 8f reaches a different height for every gravity.

challenge icon

Challenge

Medium

Two jumpers run the same Jumper.cs: the Kid, whose Inspector sets gravity to -18 and jumpHeight to 1, and the Kangaroo, with gravity -8 and jumpHeight 4. Space sets verticalSpeed to 9, a number found by trial and error: it fits neither jumper, and it works in mid-air too. Fix the jump:

  • Space starts a jump that rises exactly jumpHeight, worked out from each jumper's own jumpHeight and gravity.
  • Only a grounded jumper can jump.

Press Play and jump, then Check.

Try it yourself

using UnityEngine;

public class Jumper : MonoBehaviour
{
    public float speed = 5f;
    public float gravity = -18f;
    public float jumpHeight = 1f;

    CharacterController controller;
    float verticalSpeed;

    void Start()
    {
        controller = GetComponent<CharacterController>();
    }

    void Update()
    {
        if (controller.isGrounded && verticalSpeed < 0f)
        {
            verticalSpeed = -2f;
        }
        if (Input.GetButtonDown("Jump"))
        {
            verticalSpeed = 9f;
        }
        verticalSpeed += gravity * Time.deltaTime;

        Vector3 move = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical")) * speed;
        move.y = verticalSpeed;
        controller.Move(move * Time.deltaTime);
    }
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Building Real Games