fbpx
Read Time:8 Minute, 14 Second

In a previous guide, we have explained how to add player movement in Unity.
In this guide, we will extend the movement options for the player and add sprinting and jumping in Unity.

This guide uses the script we have written in the previous guide so be sure to check it out.

Player Movement – Sprinting

If we think about it, the only difference between walking and running is the movement speed.
As you might know, in different games, there are different running mechanisms. In some games, you toggle running and in others, you must hold down the sprinting button. In this tutorial, we will implement the latter.

Using our script from the previous guide, add a field to the PlayerMovement class called “runningSpeed” and give it a default value of 15.

// A field for the player's running speed
public float runningSpeed = 15f;

Now, when the player holds down the left shift, we want to use this speed instead of the walking speed.
To do that, we will use an if-else statement – If the left shift key is held down, use runningSpeed. Else, use speed.

// If left shift is held down, use the runningSpeed as the speed
if (Input.GetKey(KeyCode.LeftShift)) {
    rb.AddForce(movementDirection * runningSpeed, ForceMode.Force);
}
// Else (left shift is not held down) use the normal speed
else {
    // Move the player
    rb.AddForce(movementDirection * speed, ForceMode.Force);
}

Nice, now our player can run when holding down left shift, and we have completed the “spriting” part of sprinting and jumping in Unity.

Sprinting Challenge

We have just implemented running while holding down the left shift, but as mentioned earlier, there is another type of running – toggle.
Think you can code it yourself? You are hereby challenged!
Let us know how it went in the comments below.

Player Movement – Jumping

Some Explanation

What is jumping? We are not trying to start a philosophic or a sports discussion, it will just help us understand how to add jumping to our player game object.
Jumping is applying bursting force in a certain direction, usually upward.
Luckily for us, using the physics provided by the Rigidbody component, Unity enables us to do just that.

To do that, we will use a method we already used in our last guide which is “AddForce”.
The method is pretty much self-explanatory, it adds force to an object.
Its first argument is a Vector3 variable, describing the direction the force should be applied to while the second is the force type.
In the previous guide, we used “ForceMode.Force”. This tells Unity to apply a continuous force in the given direction. This time, we will use “ForceMode.Impulse”. This tells Unity to apply the force once in a given direction.

Getting practical

To implement the jump, add a new field to the class.

// A field for the player's jump force
public float jumpForce = 5f;

Also, add the following code to the end of the Update method.

// If space is pressed, add force in an upward direction (jump)
if (Input.GetKeyDown(KeyCode.Space)) {
    // Add force in an upward direction (jump)
    rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
}

Now, save the script, go back to Unity and enter play mode. We can jump! But wait… our player game object is not falling to the ground as expected…

This is happening because, in our previous guide, we manually changed the drag so the player will not slide when releasing the movement keys. But in the air, we want him to fall back to the ground as expected.

Another issue we have, is the player can jump while in the air. In this case we do not want the player to be able to do that. We want him to only be able to jump while he is on the ground.

Let us fix the latter first.
To do that, we need to know when the player is on the ground and only then allow him to jump. To do that, we will add a short ray cast from the player downward, and only when it collides with an object (for example, the ground), the user will be able to jump.

Add the following code to the start of your Update method.

// Shout a short raycast downward to check if the player is standing on something
float gameObjectHeight = gameObject.transform.localScale.y;
isOnGround = Physics.Raycast(transform.position, Vector3.down, gameObjectHeight + 0.1f);

Now that we can tell whther the player is on something or not, we can check if he is on something when trying to jump. Change the if statement from this:

if (Input.GetKeyDown(KeyCode.Space))

To this:

if (Input.GetKeyDown(KeyCode.Space) && isOnGround)

Now the player can only jump when standing on something and by now, your code should look like this:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMovement : MonoBehaviour
{
    private float horizontalMovement;
    private float verticalMovement;

    // A field editable from inside Unity with a default value of 5
    public float speed = 5.0f;

    // A field for the player's running speed
    public float runningSpeed = 15f;

    // A field for the player's jump force
    public float jumpForce = 5f;

    // How much will the player slide on the ground
    // The lower the value, the greater distance the user will slide
    public float drag;

    private Rigidbody rb;
    private bool isOnGround;

    // Start is called before the first frame update
    void Start()
    {
        rb = GetComponent<Rigidbody>();
        rb.freezeRotation = true;
    }

    // Update is called once per frame
    void Update()
    {
        // Shoot a short raycast downward to check if the player is standing on something
        float gameObjectHeight = gameObject.transform.localScale.y;
        isOnGround = Physics.Raycast(transform.position, Vector3.down, gameObjectHeight + 0.1f);

        // This will detect forward and backward movement
        horizontalMovement = Input.GetAxisRaw("Horizontal");

        // This will detect sideways movement
        verticalMovement = Input.GetAxisRaw("Vertical");

        // Calculate the direction to move the player
        Vector3 movementDirection = transform.forward * verticalMovement + transform.right * horizontalMovement;
        
        // If left shift is held down, use the runningSpeed as the speed
        if (Input.GetKey(KeyCode.LeftShift))
        {
            rb.AddForce(movementDirection * runningSpeed, ForceMode.Force);
        }
        // Else (left shift is not held down) use the normal speed
        else
        {
            // Move the player
            rb.AddForce(movementDirection * speed, ForceMode.Force);
        }

        // Apply drag
        rb.drag = drag;

        // If space is pressed, add force in an upward direction (jump)
        if (Input.GetKeyDown(KeyCode.Space) && isOnGround)
        {
            // Add force in an upward direction (jump)
            rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
        }
    }
}

Now let us fix the drag.
When the player is on the ground, we do want to edit the drag but when he is in the air, we don’t want any drag. So we will add another if statement to check if the user is on the ground. If he is, we will edit the drag. If he is not, we will set it to zero.

Change this:

// Apply drag
rb.drag = drag;

To this:

// Apply drag only if on the ground
if (isOnGround) {
    rb.drag = drag;
}
else
{
    rb.drag = 0;
}

And move this code underneath this line:

// Calculate the direction to move the player
Vector3 movementDirection = transform.forward * verticalMovement + transform.right * horizontalMovement;

By now, your code should look like this:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMovement : MonoBehaviour
{
    private float horizontalMovement;
    private float verticalMovement;

    // A field editable from inside Unity with a default value of 5
    public float speed = 5.0f;

    // A field for the player's running speed
    public float runningSpeed = 15f;

    // A field for the player's jump force
    public float jumpForce = 5f;

    // How much will the player slide on the ground
    // The lower the value, the greater distance the user will slide
    public float drag;

    private Rigidbody rb;
    private bool isOnGround;

    // Start is called before the first frame update
    void Start()
    {
        rb = GetComponent<Rigidbody>();
        rb.freezeRotation = true;
    }

    // Update is called once per frame
    void Update()
    {
        // Shout a short raycast downward to check if the player is standing on something
        float gameObjectHeight = gameObject.transform.localScale.y;
        isOnGround = Physics.Raycast(transform.position, Vector3.down, gameObjectHeight + 0.1f);

        // This will detect forward and backward movement
        horizontalMovement = Input.GetAxisRaw("Horizontal");

        // This will detect sideways movement
        verticalMovement = Input.GetAxisRaw("Vertical");

        // Calculate the direction to move the player
        Vector3 movementDirection = transform.forward * verticalMovement + transform.right * horizontalMovement;
        
        // Apply drag only if on the ground
        if (isOnGround)
        {
            rb.drag = drag;
        }
        else
        {
            rb.drag = 0;
        }
        // If left shift is held down, use the runningSpeed as the speed
        if (Input.GetKey(KeyCode.LeftShift))
        {
            rb.AddForce(movementDirection * runningSpeed, ForceMode.Force);
        }
        // Else (left shift is not held down) use the normal speed
        else
        {
            // Move the player
            rb.AddForce(movementDirection * speed, ForceMode.Force);
        }

        // If space is pressed, add force in an upward direction (jump)
        if (Input.GetKeyDown(KeyCode.Space) && isOnGround)
        {
            // Add force in an upward direction (jump)
            rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
        }
    }
}

Save the script, go back to Unity and enter play mode. As you can see, the player can now jump only while standing on something and he falls to the ground as expected but now he moves too fast while in the air. Let us fix that too.

Add a new field to the PlayerMovement class called “airMultiplier”.

// A field for the player's speed multiplier while jumping
public float airMultiplier;

Add the following to the if statement, where we check if the player is on the ground, to the else part.

movementDirection *= airMultiplier;

So now, or if statement should look like this:

// Apply drag only if on the ground
if (isOnGround)
{
    rb.drag = drag;
}
else
{
    movementDirection *= airMultiplier;
    rb.drag = 0;
}

And there you have it, sprinting and jumping in Unity.

Recap

In this guide we:

  • Enabled the player to run when holding down the left shift key.
  • We understood what is jumping.
  • We implemented jumping functionality and tackled a few issues we need to fix:
    • Falling back to the ground.
    • The player can jump while in the air.
    • The player moves too fast while in the air.

Now you have a player who can walk around, sprint and jump.

Leave a Reply

Your email address will not be published.