Unity RPG: Character Controller

Step 1
In this lesson we will create a player GameObject which can move around a test scene

The movement includes:

  • walking, running, and turning
  • smooth wall collisions
  • ability to walk up and down slopes/stairs
Step 2
We are going to learn to use a Character Controller
Step 3
Start of course with a new empty project and then import these assets


Download RPG_Assets.zip Download Updated_CodeBot.zip

Once you've downloaded the folder, drag and drop the contents to your project's Asset Folder

Step 4
Inside of the "RPG Assets" folder open the Scene named "myScene"

Double click the Scene file and it should open to reveal this Scene:

Step 5
This will be our character in this course: "MVCodeBot"

MVCodeBot comes pre-programmed with the animations we'll need for the movement options and abilities we will create in this course.

You can change the character as you like once you've finished the course

Step 6
This will be our character in this course: "MVCodeBot"

MVCodeBot comes pre-programmed with the animations we'll need for the movement options and abilities we will create in this course.

Step 7
We'll start by adding a CharacterController component to MVCodeBot

The CharacterController has a handy method named Move() which handles collisions and slopes for us.

We'll make use of that soon!

Step 8
Notice the character controller has its own collider (the green capsule).

We'll need to center and scale this properly around the character

Step 9
Change the Center, Radius, and Height properties and fit the capsule around MVCodeBot

You can always come back and fix it later if it's not perfect.

Step 10
Next we're going to add a new script "playerController" to our bot

The CharacterController does very little by itself, but it makes the coding much simpler.

Step 11
Open the script and create a function named Movement()

This will handle walking, running, and eventually jumping.

Step 12
Looking at our bot from the top, we can see that the player shall walk in the X and Z directions only

The Z-Direction is forwards and backwards, while the X-Direction is left and right.

Step 13
Using Input.GetAxisRaw() we can store the value of the Vertical and Horizontal axes

GetAxisRaw() returns 1, 0, or -1 depending on the direction pressed on the keyboard

Record these values in floats x and z

Step 14
Create a new Vector3 using the X and Z inputs we just obtained

The purple line shows how this Vector can be visualized.

X, (Y == 0), and Z combined = Velocity Vector

Step 15
Okay so let's try using this Vector to make our character move. We'll need to use the CharacterController

We'll need to

  • reference the CharacterController.
  • set a moveSpeed float for the player.
  • use the CharacterController's .Move() method with our velocity Vector.
Check Your Work
Step 16
Think of this as taking the entire component and stuffing it into "cc"

cc had to be CharacterController type in order to hold a CharacterController.

Step 17
Create a CharacterController variable named "cc"

Then use GetComponent<> to set this variable to our Player's

Step 18
Create a float named moveSpeed

You could make this public if you want to play with it in the Inspector while the game is running

Step 19
Multiplying the velocity Vector by the moveSpeed float gives us the a vector which indicates how far to move

Example where moveSpeed is equal to 3 instead of 10:

We're also going to scale by Time.deltaTime which makes it "how far per second" rather than "how far per frame" as it would be without it.

Step 20
Call the Move() function of the CharacterController class

Pass it the velocity vector we just created.

Step 21
Now call the Movement function from Update so that it activates every frame
Check Your Work
Step 22
You should be able to move the character around when you hit Play

Note that you can use either WASD or the arrow keys. Both of which activate Input.GetAxis()

Step 23
Normalizing the velocity

Watch the length of the vector as it heads North-East. What happens to the length?

Compare this to a Normalized vector which always has the same length:

Do you remember normalization from our Roll-A-Ball course?

Step 24
Watch how much faster our character moves diagonally

Our direction vector should always have a length of 1 before we scale it (multiply) by moveSpeed.

Demonstration Comparison: Without normalizing

vs. With Normalizing:

Step 25
Go back to your movement function and create a new Vector3 named direction

direction will be equal to the normalized input vector

Step 26
Now we're going to replace this part of our velocity initialization with "direction"

It should look like this:

Velocity is direction x speed.

Check Your Work
Step 27
Now our player moves at the same speed in every direction

Next we'll make the character face the direction they are moving:

Step 28
To make the player face the direction they are moving, we need to rotate around their Y-axis

Imagine sticking a pole through the Y-Axis of the player and spinning them around

Step 29
We need to find the ANGLE (Θ) of the velocity vector

We use the symbol "theta" written Θ for angle.

Step 30
To find the angle we will be using a math function called the ARCTANGENT

The Arctangent of a vector will give us the angle we need

Press play to watch the slideshow

Step 31
Create a float to store the y-direction
Step 32
Next we're going to use the arctangent function Math.Atan2

Atan2() makes things easier for us than Atan(). It's a long story...

Step 33
Now we are in the components of the Slope
Step 34
Lastly we use Rad2Deg to convert from RADIANS to DEGREES

Radians is the default way of measuring angles, but we need to measure in Degrees.

Multiplying by Rad2Deg does this for us

Step 35
Now we can set the local y-rotation to yAngle

We are only rotating around the Y-Axis so:

X = 0
Y = yAngle
Z = 0

Euler angles are the xyz-rotations in you are used to by now

Check Your Work
Step 36
They player can now around around and will always face the direction they are moving in

Now you're probably hoping we deal with the issue of having no gravity...

Step 37
How will we model gravity?

We'll define gravity as a value that:

  • is 0 if the player is on the ground
  • otherwise moves the player down
  • increases as long as the player is in the air (to a maximum value)
Step 38
Start by created a global float named "gravity"

Note that this is really the player's gravity measure. Other objects will need their own gravity's.

Step 39
We can use the CharacterController to check if the player is on the ground on not

Another great use of the CharacterController is the isGrounded property:

If the player isn't grounded then we need to increase gravity.

Step 40
First add an if statement to set gravity to 0 if the player is on solid ground

Remember that we've named our CharacterController "cc".

So we need to write cc.isGrounded

Step 41
Now we can use an "else" to write what happens if the player is NOT grounded

We should now increase the value of gravity

Step 42
Also we're going to clamp gravity here to be between 1 and 20

This makes sure our player never falls too fast and also prevents some floating behavior by starting gravity at 1

Step 43
Now we may have a gravity value, but we haven't told it to make our character fall yet

We need to create a downward Vector to add to our velocity.

The length of the vector will be the value of gravity.

Step 44
Construct a gravity vector
Step 45
The CharacterController should Move along the combined "velocity" and "gravity" vectors:

Note that we combine Vectors by adding them together

Check Your Work
Step 46
Now our character moves around and falls nicely
Step 47
Before we call this lesson finished there is a slight tweak we should make

When you let go of all directions we see the player returns to facing forward:

So let's only have the direction update if the player is actually moving

Step 48
If the MAGNITUDE of the velocity is greater than 0, we know the player is moving

Only change direction if the player is actually moving

Check Your Work
Step 49
The player should now always face the last direction they were moving
Step 50
In the next lesson we will learn about State Machines by adding a Jump function

Once we understand State Machines we will be adding our Animations to the movement of our palyer

Unity RPG: Character Controller Info



Created By



Build an RPG in Unity

Access Level


For Teachers and Schools

Teach coding to your students with MVCode Teach

MVCode offers an integrated product designed to teach coding to students.

Learn more about MVCode Teach