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
MediumMake one jump script fit both the Kid and the Kangaroo.
- In
Update(), replace9fwithMathf.Sqrt(jumpHeight * -2f * gravity), the start speed that rises exactlyjumpHeight. - Add
&& controller.isGroundedto the jump'sif, 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
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 SwapPractice on your own: Unity playground