Menu
CoddyTech

Jumping

Part of the Building Real Games section of Coddy's Unity journey. Lesson 40 of 60.

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

Make one jump script fit both the Kid and the Kangaroo.

  1. In Update(), replace 9f with Mathf.Sqrt(jumpHeight * -2f * gravity), the start speed that rises exactly jumpHeight.
  2. Add && controller.isGrounded to the jump's if, so there is no jump in mid-air.

Press Play and Space: the Kid rises 1 unit and the Kangaroo 4. 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);
    }
}

All lessons in Building Real Games

Practice on your own: Unity playground