Skip to main content

This tutorial will show you how to extend a simple player controller for Unity by adding the ability to jump and shoot projectiles.

Firstly this tutorial is design to follow on from the previous tutorial that shows you how to create a simple player controller using Unity.


Setup

A good place to start is to make a duplicate of the initial scene created in this project and call it something like ‘Extended Player Controls’ (or whatever works for you).

You can duplicate a scene by first selecting it in the assets and then in the Edit menu select Duplicate. Then make sure that you have this scene selected as the scene you are currently editing.

In your assets panel find the BasicPlayerController script that you made in the last tutorial and duplicate that also. Rename it ExtendedPlayerController snd in the actual script make sure the class name matched the name of the script. This is important or the script will throw an error.

public class ExtendedPlayerController : MonoBehaviour
//..

Then in the inspector deselect your Basic Player Controller script. Then drag your Extended Player Controller script onto the bottom of the inspector area to add it to the player object.

Adding extended player controller script.
Adding extended player controller script.

* Because this is essentially a new script added to the player object, with the player object selected in the inspector you will need to add the Camera Target object and the Movement Intensity value (not show in the picture above). This is the same process that you had to do for the Basic Player Controller script.

Now, in theory we should have a backup of the previous tutorial in its own scene and a new scene and version of the player controller script ready to update within the same Unity project.

* If you look at the script for this version I decided to apply the movement based on velocity rather than force. As mentioned in the previous tutorial this makes the controls a bit more responsive, however the force movement is still there if you want it, just commented out.

Part 1 – Make a Projectile Prefab

Create a prefab object that will be used for your projectile.

You can do this by first creating the object in the hierarchy, adding materials to it etc, then dragging it from the hierarchy to the assets. (* you can also edit it once it is a prefab). The main thing is that prefabs are good for making multiple instances of the same element. – Changes made to the prefab object will be inherited by all the instances of the prefab.

In this example I am creating the prefab as a 3D cube and then adding:

  1. The checkerboard image
  2. A rigid body component
  3. Our Bouncy physics material
  4. Resize it to 0.25, 0.25, 0.25 (x,y,z).

Once you have made the prefab object and it is in your assets delete it from the game hierarchy. – We will now write a basic instantiation script that will place instances of the projectile prefab object into the game with force applied, when the user presses the space bar key.

Projectile prefab in the assets

Part 2 – Add a Shoot Script

* I won’t include the entire script here. I will step you through the new bits of code we will add to our existing Player Controller script.

First, at the top where we declare our variables add:

public GameObject Projectile;
/*
Creates a variable for our Projectile.
In this example this must be a prefab 
with a rigid body component
*/

Then within the update function add:

// shoot
if (Input.GetKeyDown(KeyCode.Space)) {
    shootProjectile();
}
/*
Calls a 'shootProjectile' function
when the space key is pressed.
*/

Then after the update function (and not within it) add the shoot function. * This is after the closing curly brace the identifies the end of the void Update() function. If you are confused about this you can review the entire code on Github.

void shootProjectile()
{
    var ForwardDirection = cameraTarget.transform.forward;
    var RightDirection = cameraTarget.transform.right;
    var UpDirection = cameraTarget.transform.up;

    GameObject clone = Instantiate(Projectile, transform.position + 1 * ForwardDirection, transform.rotation);

    clone.GetComponent<Rigidbody>().AddForce(ForwardDirection * 600);
    clone.GetComponent<Rigidbody>().AddForce(UpDirection * 200);
    clone.GetComponent<Rigidbody>().AddTorque(RightDirection * 200);

    Destroy(clone, 5.0f); // Destroy the clone after 5 seconds

}    

* Don’t forget you will need set you projectile object by first selecting the player object and then drag the projectile prefab from the assets into the slot for ‘Projectile’.

This code is a little bit clumsy for the time being and I am hoping to tidy this up a bit soon. You can imagine that rather than using numbers for the force directions of the projectile you could create public variables for these values so they could be accessibility from Unity. I also want to get a better system for adding the the torque.

Part 3 – Add a Jump and a Condition That the Player Controls Only Work When the Object Is ‘Grounded’

Add the following variables, and don’t forget to later add values to these in Unity.

// Variables for jump
public Vector3 jump;
public float jumpForce = 2.0f;
public bool isGrounded;

* These controls add the jump as a vector which means you can control the values of jump in all directions from within Unity. Once all this code is added I would suggest starting with a Y value of 4 on the Jump (in the inspector in Unity).

Then within the update function add:

// jump
if(Input.GetKeyDown(KeyCode.X))
{
    rb.AddForce(jump * jumpForce, ForceMode.Impulse);
    isGrounded = false;
}

If you want to make it so the player controls only work when the player is grounded, add the following script to the update function and put any scripts you want to be conditional upon the player being grounded inside the curly braces. Again you may want to review the final script on Github if you are unsure about this.

if (isGrounded) 
{

// Move your other functions inside this condition

}

And add the following functions to root level of the script (ie, not inside the update function, after the shoot projectile function).

void OnCollisionStay()
{
    isGrounded = true;
}

void OnCollisionExit()
{
    isGrounded = false;
}

This code basically sets the isGrounded value to true or false depending on whether the player stays in contact or say a state of collision with another object. * This is not entirely perfect but it generally works well with the ground plane object.

Now the player should only move when grounded, and you can jump and shoot projectiles. What is fun to do here is to add a whole bunch of rigid body objects and interact with them.


If you would like to stay in the loop when I publish new tutorials you might want to consider subscribing to my Youtube Channel, or if you use RSS you can find feeds available for any or all of my tutorial categories.

If you're into game development you may also be interested in some of my articles relating to game design and development.

I would love to make it my thing to create high quality tutorials that are 100% free with no strings attached.

If this tutorial was useful for you please consider showing your appreciation and offering your support. It will make my day!

Buy me a coffee

Filed under:
Game Development, Unity

Similar Tutorials:

All Tutorials

Henry Egloff
Twitter Twitter 2 Facebook Linked In Instagram Codepen Behance Youtube Opensea Heart