unity character controller

Unity Character Controller: FREE Tutorial #4 Multiplayer MMO Game

Unity 3D MMO Tutorial Series

Hello and welcome to the Unity Character Controller Strafing, Rotating, and Moving tutorial. You have made it to tutorial number 4. If you have not completed the third tutorial, go back and finish it. You can find the tutorial here. If you are looking for the first tutorial, you can find it here.

This tutorial will be the longest so far. The first thing I want to do is change the name of an existing variable. Let’s change the name of the Vector2 “inputs.” In your “PlayerControls.cs” script, double-click the word “inputs.” right-click, and click rename. Rename this variable to “keyboardInput” and press enter. Rename changes all lines with “inputs” to “keyboardInput.” Changing the name makes the variable clearer, more concise, and less confusing.

Let’s Get Strafing!

Now that we have some forward and backward movements code, we need to implement the strafing code. The code behaves like forward and backward, except for some substitutions to make the character step left and right.

Instead of “keyboardInput.y”, we will use “keyboardInput.x”. We use the X-axis here because we want the character to move from side to side. With the new code, we add to the “void GetInputs()” method:

 if (Input.GetKey(baseControls.strafeRight))
 {
     keyboardInput.x = 1;
 }

So, you probably have a pretty good idea of the next part of the code.

if (Input.GetKey(baseControls.strafeLeft))
{
    if (Input.GetKey(baseControls.strafeRight))
    {
        keyboardInput.x = 0;
    }
    else
    {
        keyboardInput.x = -1;
    }
}

The Y-axis has a built-in check to ensure the player hasn’t pressed the W and S buttons simultaneously. The X-axis serves the same purpose. We wrote code that will check to determine if the player pressed a key. If the player is not strafing, “keyboardInput.x” is zero.

if ((!Input.GetKey(baseControls.strafeRight)) && !Input.GetKey(baseControls.strafeLeft))
{
    keyboardInput.x = 0;
}

What’s It Doing?

What’s the game doing when you press play? Well, so far, not much. When pressing the Q key, the X value in Keyboard Input becomes -1. Same for the E key, except the X value is positive 1. Try pressing both the Q and E at the same time. The X value is Zero.

unity character controller
Q Pressed, X Value is -1

Rotation Rotation Rotation!

In this next Unity Character Controller MMO Tutorial #4 section, I will show you how to rotate the character. Or at least how to get the rotation keys to respond. When you are ready, let’s make it happen!

I first added a variable of the type “float,” containing a decimal point. The variable is called “rotation.”

 public float rotation;

I placed the code above the “Start()” method with the other class variables. Class variables are inserted above the method blocks for readability and scope. You can read about “scope” here.

Look in the Inspector tab with the “Player” selected. You will notice there is now a Rotation field listed indicating zero.

unity character controller
Rotation Field

Now I will show you the rotation code. As you might have guessed, the code is the same as the others for strafe, forward, and backward. Put this code at the bottom of the GetIputs() method. Don’t worry that the code is getting long. We will streamline the code in a later tutorial.

So, here is the code:

if (Input.GetKey(baseControls.rotateRight))
{
     rotation = 1;
}

As before, pressing the D key will set the rotation to 1. However, there is no X or Y value. We will code a calculation for the rotation soon. Here is the rest of the code for rotation:

if (Input.GetKey(baseControls.rotateLeft))
{
    if (Input.GetKey(baseControls.rotateRight))
    {
        rotation = 0;
    }
    else
    {
        rotation = -1;
    }   
 }
if ((!Input.GetKey(baseControls.rotateLeft)) && !Input.GetKey(baseControls.rotateRight))
{
     rotation = 0;
 
}

Keep in mind that A will rotate the Player left. Run your game and make sure that rotation works properly by pressing “A or D and A + D.”

Locomotion Is The Motion!

We’re getting closer to making the character move! I added a new method and named it “Locomotion.” Place the new method under the “Update()” method and call the method from the “Update().” Calling a method means you are using the method. In this case, “Update()” uses the method once every frame.

void Update()
{
    GetInputs();
    Locomotion();
}
public void Locomotion()
{
       
}

Now that we have the method, start coding the action!

Create a new variable of type “float.” Initialize the float to 1f. If a decimal point was intended, the small letter “f” must be present. Name the float “walkSpeed.”

Place the variable at the top of the class under the other variables. We now have a shiny new variable in the Inspector! Notice because we hardcoded “walkSpeed” to 1f, it now has a 1 next to Walk Speed in the Inspector.

public BaseControls baseControls;
public Vector2 keyboardInput;
public float rotation;
public float walkSpeed = 1f;
unity character controller
Walk Speed

Now at the top of the Locomotion method, we will make another variable of type float and name it “speed.” Make “speed = walkSpeed.” Since the variable “walkSpeed” is of type “float,” we can compare the two variables.

float speed = walkSpeed;

Who Gives A Bool?

Let’s introduce a new type of variable. This variable is of type “bool.” This type of variable will let you ask a yes or no question. More precisely, a true or false statement. Type the code like this:

public bool run = true;

I declared the variable “public” and initialized it to “true.” I set the variable “run” to true because I want the character to run instead of walk when the game starts.

So far, I have five variables at the top of the class and one in the Locomotion method.

public BaseControls baseControls;
public Vector2 keyboardInput;
public float rotation;
public float walkSpeed = 1f;
public bool run = true;
 public void Locomotion()
 {
     float speed = walkSpeed;
 }

We need an “if” statement to toggle the walk/run speed. Remember that the forward slash on the number pad will toggle this code. In the “Locomotion” method, place the following code: (NOTE: the “runSpeed” will cause an error. We will fix that soon.)

if (run)
{
    speed = walkSpeed * runSpeed;
}
else
{
    speed = walkSpeed;
}
if (keyboardInput.y < 0)
{
    speed = walkSpeed;
}

This code block will change the player’s speed based on whether the “run” variable is true or false by pressing the Keypad Divide button. If the “run” variable is true, the player’s speed is set to walkSpeed * runSpeed, which results in the player moving faster. The “else” statement reverts the player’s speed to “walkSpeed” if the “run” variable is false.

The second if statement, “if (keyboardInput.y < 0)”, checks if the player is moving backward. If the player is moving backward, the speed is set back to walkSpeed, which means the player will move slower when moving backward. We did this to make the gameplay feel more natural because it is harder to move backward quickly in real life.

Notice that the Run tick box was checked as “true.”

unity character controller
Run Tick Box Is Checked

I also need a way to make “run” equal to “false.” I can do this by creating an “if” statement. Place the following code at the top of the “GetInputs()” method:

if (Input.GetKeyDown(baseControls.runWalk))
{
    run = !run;
}

If you remember, “runWalk” is declared in the BaseControls.cs file. We set it to the Forward Slash key(/) in the Numpad.

More Variables

I need to declare a couple of more variables. I created a variable for the “runSpeed,” and a variable for the “rotationSpeed.” Both of these variables are floats. I will add the two new variables to the “walkSpeed” line like this:

 public float walkSpeed = 1f, runSpeed = 5f, rotationSpeed = 500f;

I initialized the numbers on how I wanted the character to run, walk, and rotate. The Inspector grants the ability to change these values based on the user’s preferences. In World of Warcraft, the character can turn very quickly, so I used a value of 500.

unity character controller
Speed Variables

No Guts, No Glory! The Unity Character Controller

We will add the “guts” to the code now that is necessary to make this little guy move.

We need to attach the Unity Character Controller Component that we set up in tutorial #2 to the script. Do this by making a “CharacterController” type variable. Above the Start() method, type:

CharacterController controller;

We need to fill this variable with the actual “CharacterController” Component. Place the code inside of the “Start()” method.

controller = GetComponent<CharacterController>();

We need a “Vector3” type variable to make this dude move. A vector 3 holds the values for the X-axis, Y-axis, and Z-axis. So, if I make a variable named “velocity,” velocity would, for example, look like this inside: Vector3(12.1f, 24.7f, 0f).

I declared the following “Vector3” variable above the “Start()” method:

Vector3 velocity;

We must fill the variable “velocity” with something. Let’s make a calculation that will get the character object to move. The definition of velocity is “The speed of something in a given direction.” You can read more about velocity here.

Inside the “Locomotion()” method, add the following code:

velocity = speed * Time.deltaTime * (transform.forward * keyboardInput.y + transform.right * keyboardInput.x);

The line of code takes the transforms of the object we want to move (in this case, the player character) and multiplies them by the speed we want the character to move.

There’s one more thing to do before the guy can move: add the Unity Character Controller move method like this to the “Locomotion” method:

controller.Move(velocity);

CharacterController.Move is a Unity Scripting API required to make the character move. The API passes in our velocity variable. You can read about it here.

Drum Roll, Please!

Press play, press the W, S, Q, or E keys, and watch the character move! The Player object may not appear to be moving because we don’t have any scenery to watch fly by.

There are two things we can do. The first is looking in the Inspector to see the X and Z values change.

Unity Character Controller
X and Y Values Change

Notice that the Y-Axis has a value of 0.0999999. The value is because the Character Controller capsule is not precisely at the bottom of the character’s feet. Some tweaking of the Center Y and Height numbers can fix this. For now, It is good enough.

The second thing is to scale down the Ground Plane to something more manageable. This way, you can see the Player moving from side to side, forward and backward. I scaled mine down to 2 across the board. We can change it back at any time.

unity character controller
Ground Plane Scaled Down To 2

Press the forward slash key(/) on the Numpad. You will notice that the forward movement has slowed because pressing the Run Walk key will make “run” equal to “false” and uncheck Run in the Inspector.

Camera, Action!

I want to fix the camera before moving on. My camera is set too far behind the Player character, so I need to move it closer and rotate it to look at the Player character.

Open up the Player in the Hierarchy and click on Main Camera. This will set the gizmo on the camera, and we can move it forward and up. We can also rotate it to fit our needs.

unity character controller
The Main Camera Moved Into Position

Gravity Of The Situation

We should add some gravity to the character. We code our gravity rather than using the built-in gravity. In the Player Inspector, click Add Component and search for “Rigidbody.” Add the component to the Player.

The rigidbody component allows the Player Character to use the Physics and Collision Detection we need for the game. Learn more about Rigidbody here.

unity character controller
Rigidbody Component

The “Use Gravity” is ticked. However, it won’t work at this juncture. We need to attach the code to the Rigidbody Component. Add the following variable declaration under the “CharcterController” variable:

Rigidbody rb;

Now, I filled the “Rigidbody rb” with the Rigidbody Component by typing in the “Start()” method:

 rb = GetComponent<Rigidbody>();

Let’s Make Our Gravity

We need to write code to simulate our gravity because we will use the “Is Kinematic” selection later for animation. Using the kinematic option does not work with the built-in gravity, so coding our own is the best option.

We will add the gravity code at this time. Declare a “public float gravity” at the top with the other variables and initialize it to 8f.

 public float rotation;
 public float walkSpeed = 1f, runSpeed = 5f, rotationSpeed = 500f;
 public float gravity = 8f;

We will add the “gravity” to the “velocity.y” because we want the “Player” to be continuously “pulled” down. Therefore the code must be inserted into the “Locomotion()” method under “velocity = speed…”:

velocity.y -= gravity * Time.deltaTime;

The code block will read: “velocity.y minus velocity.y equals gravity times Time.deltaTime”. In every frame, the character will “try” to achieve a negative in the Y-Axis, but the rigidbody component’s collision won’t let it until it steps off the edge of the Ground Plane.

Un-tick the “Use Gravity” box in the Rigidbody Component. Run the game and watch the character fall off the edge of the Ground Plane!

Last But Not Least…

I can’t end the tutorial without adding the rotation calculation. If the Player character can’t rotate, it can’t run around the sandbox correctly. Let’s do this!

It won’t take much code to get the rotation working. However, the code is a bit complicated. I will try my best to help you make sense of it. We will create a “Vector3” called “characterRotation.” The “Vector3” will be initialized with a calculation. Add the following code to the top of the “Locomotion()” method:

Vector3 characterRotation = transform.eulerAngles + new Vector3(0, rotation * rotationSpeed, 0) * Time.deltaTime;

The “transform.eulerAngles” stores the rotation of an object relative to the world coordinate structure in the form of a “Vector3.” A new “Vector3” is added to the transform and multiplies the rotation times the rotationSpeed in the Y-Axis. The above code “sets” the rotation of the object.

The next part “gets” the object’s rotation and applies it. Add the following code below the Vector3 code:

transform.eulerAngles = characterRotation;

Save the script and press play. Now your character should be able to rotate by pressing the A key or the D key!

Congratulations on coming this far! In the next tutorial, I will show you how I got the mouse controls to behave similarly to WOW.

Until next time, May The Force Be With You, Always. – Dragon

Tagged

1 thought on “Unity Character Controller: FREE Tutorial #4 Multiplayer MMO Game

  1. Wow! This blog looks exactly like my old one! It’s on a completely different topic bbut it has pretty much the same page layout and design. Supperb
    choice of colors!

    my site Debora

Leave a Reply

Your email address will not be published. Required fields are marked *