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
MediumTwo 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 ownjumpHeightandgravity. - 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);
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Building Real Games
2Buttons and Screens
Buttons and onClickLambdasWiring in the InspectorPanels On and OffHealth BarsRecap: Upgrade Shop5Saving with PlayerPrefs
Save a NumberLoad with a DefaultHigh ScoreSave SettingsRecap: Coins in the Bank8Character Controller
CharacterController.MoveGravity by HandJumpingPushing ThingsMove Where You LookRecap: Double Jump3The Game Manager
One Script Runs the GameThe SingletonGame StatesSwitching on the StateRecap: Round Manager6Project: Endless Runner
Three LanesObstacles Ahead9The New Input System
Two Input SystemsKeyboard and MousePressed This FrameInput ActionsRecap: Input Swap