Unity3D: 3rd person basic movement/rotation w/source
My original version of doing movement was a pretty sloppy hacked version. I provided the source, but it was almost impossible to really figure out what was going on. I didn’t really know what was happening, but felt good because it worked. I went back and really cut down all the code to the minimum and explained it with a lot more comments. This post explains some of the basic elements to get that 3rd person character moving and rotating.
On the 3rd person character controller script with the 3D platform tutorial that Unity provides, there is over 450+ lines of code describing how the character moves around. After studying it for a while, the most important parts of the script can be hard to spot with all of the different variables and other functionality. For this post, I just wanted to narrow it down to basic movement and rotation.
My example still has about 30 lines of code for the basics (over 40 with commenting).
Controls: W,A,S,D move OR arrow keys
Setup:
If you want to start from scratch, you can start a new project and add an object you want to control and move. You can also start with a setup project that I made. There is no gravity, physics, or collisions implemented with this explanation/tutorial, so you don’t have to create a ground plane for your character to fall on. Just add a gameObject to the stage and add a script to the object. Add a character controller component to your character game object. If you are using my set up file, just open the charactermovement.js script and you’re ready.
Nothing happens if you play the game now, since there is only one script and it is empty. Everything from this point on will be dealing with the script attached to the game object you want to move.
private var controller :CharacterController; controller = gameObject.GetComponent(CharacterController); private var moveDirection = Vector3.zero; private var forward = Vector3.zero; private var right = Vector3.zero;
These first lines are declared at the top of the script. They aren’t in any functions or classes. This is so that any function inside of the script can access the variables. Making them private means they can’t be accessed by the inspector.
The first line creates a variables of type CharacterController. This is a class that is used to manage movement of your controllable character. The second line sets the controller variable to the character controller component. “gameObject” is used to access the current gameobject that the script is attached to. The “GetComponent” method searches the game object for components that are attached to it. We can reference “controller” any where in the script if we want to use any character controller functions or methods.
The last three lines are setting up the movement direction and forward directions to “Vector3.zero”. This is shorthand for making a new vector3 object with the value (0,0,0). These will store the absolute move direction along with the relative forward direction.
Update function
Since movement is constantly changing, all movement and directions need to be calculated every frame. This is perfect for Unity’s predefined Update function. There are many different parts to movement so there needs to be a few different variables defining and monitoring each aspect.
function Update() { forward = transform.forward; right = Vector3(forward.z, 0, -forward.x); var horizontalInput = Input.GetAxisRaw("Horizontal"); var verticalInput = Input.GetAxisRaw("Vertical");
The first two lines are assigning the direction that the character is facing forward and right. I will explain why we need these in a little bit. The second two statements create variables that will store input values. These values will constantly change based off if you are pressing the up/down keys (vertical) or right/left keys (horizontal). The “GetAxisRaw” method is used instead of the “GetAxis” because the latter applies smoothing which will make our rotations less responsive. Add the next few lines after the previous two. Keep everything inside the Update function.
var targetDirection = horizontalInput * right + verticalInput * forward; moveDirection = Vector3.RotateTowards(moveDirection, targetDirection, 200 * Mathf.Deg2Rad * Time.deltaTime, 1000); var movement = moveDirection * Time.deltaTime * 2; controller.Move(movement);
the first part creates a targetDirection variable that makes a direction that is currently being pressed. Your horizontalInput and verticalInput variables will return values between -1 and 1. They are the magnitudes of the direction. The right and forward variables return directions as vectors.
Since your character will be rotating when you press the left/right keys, its forward position will be changing a lot. Since the forward variable is changing based off your orientation, the verticalInput needs to know which direction is facing forward. That is why the targetDirection multiplies the forward and verticalInput variables.
The right variable value is dependent on the forward variable. It takes parts of the forward direction and can calculate the angle 90 degrees to the right of it. This gives a local x axis based off the rotation. That is why the horizontalInput is multiplied by the right direction.
This is a little conceptually heavy, so you might need to think about this for a little while.
The “moveDirection” variable stores a rotation value. It gets the current rotation and goes to the target rotation over so many seconds. The third parameter in the RotateTowards method is the rotation speed. Higher value equals means faster rotation.
The “movement” variable takes the direction and multiplies it by Time.deltaTime * 2. This will slow down the movement to rotate by seconds instead of by frames. The last line actually moves the character controller by the amount.
Finishing touches
If you try to play the game now, you will see the character moving around. Fantastic!!
He seems a little stubborn and doesn’t want to turn at all though. We will fix that next.
transform.rotation = Quaternion.LookRotation(moveDirection);
this takes the transform (the main orientation of game object), and rotates it by moveDirection. We already set up moveDirection earlier for the angle we want it to be at.
Success…but wait. If you take your hand away from the controls for a second, he will auto-magically rotate back facing right. Dang!
So close. One more thing to fix that. Wrap this if statement around the last line you put in. It should look like this.
if (targetDirection != Vector3.zero) { transform.rotation = Quaternion.LookRotation(moveDirection); }
What this does is that the game object will only try to rotate if the targetDirection is NOT zero. When you take you hand away from the keyboard for a split second, the input values will show (0,0,0), so it thinks that is the target direction.
It isn’t,but it doesn’t know that. The only time that value will show is when you take your hands off, so the if statement simply ignores input when you take your hands off everything.
One last thing. Add this after the entire Update function at the bottom:
@script RequireComponent(CharacterController)
This will make sure a Character Controller component is attached to the game object that the script is attached to. If you forget to add one and you press play, this line will automatically add a component to the game object and save you from a nasty error.
Hit play and watch your character move and rotate around.
Final Thoughts
If for some reason you scrolled down to get the source without reading anything, here is the project set up files and source.
This is a good first step in understanding how basic character movement is put together. A fully done character is complicated, but understanding these concepts are fundamental to building more advanced setups. This set up might seem weird with how the character moves, but when a camera is added along with a few other elements later, it will all make sense. I will try to continue where this example leaves off and explain more with collisions and actions like jumping in the next post.







Hello
I tried your tutorial and its really good thanks. but i Have a problem.
When i press the down button (to go backwards) it does it but when i hold the button it turns and always moves in the same direction. Is there anyway to fix this.
Thx in advance
Kevin
@Kevin
The key to understanding what is going on is to realize that the character is turning and moving based off HIS current view. It doesn’t know there is a camera to know which way is left, or down, or right.
When you press the back key, it is saying “hey, look behind me”. It does a 180 at that point. if you press it again, it again says “look behind me”. Holding the back button constantly is flipping it 180 degrees. It does a slight rotation, but mostly acts sporadically.
I am guessing you want it to act more like a game where it is turning based off the CAMERA’s view. When you press left, it will go left and continue left, when you press down, it will go toward the camera.
Based with the knowledge you learned with this tutorial, you can use the third person tutorial with Lerpz from Unity and look how to do it that way. I think it is in the “ThirdPersonAnimation.js” file. There is more code, but the mechanics are similar. The biggest difference is that direction is tied to the camera instead of the actual character.
Link is down ;) and nice tutorial,
Thank you for a good explanation of the basics of 3rd person movement. I’m just starting to learn Unity and this was just what I needed to get on the right track.
Hi there,
Is this faster than transform.right?
right = Vector3(forward.z, 0, -forward.x);
Did you base this on a mathematical principle or did you just work it out by looking at it? I sense some linear algebra tickling the back of my mind; but that was a long time ago. I had to roll this out on some grid paper for a little bit before it made sense. I think that extra axis is throwing me.
I need to find a good book to assist me in mathematical approaches for gaming. I recently learned about a handy method of using dot products on vectors to compare angles, and I suspect I am missing a lot more good tools. (Things I learned in college and then forgot most likely. Thank goodness I remember a *little* of my vector math).
Thanks for the tutorial!
transform.right is probably faster. I wasn’t sure of how to actually make it work right, so I was playing around with different values. It would be easier to read as transform.right, so I would change it to that
Guys I am new to scripting but I am trying hard to understand the concept. Please help me to solve the basic problem in simply making my capsule object to move. Seems that everything I paste in dashcode doesnt work for my object even though i am just copying and pasting the very same tutorial from this page. I just have plane, main camera, and capsule object in my scene. I am trying to execute this tutorial for my capsule to move but it doesnt want to work and i am very frustrated..
Thanks a lot
This tutorial basically goes over that. Does it work if you download the project set files in the link in the post? The two main things that can go wrong is that
1. Your input isn’t picking up.
I would try to Debug.Log( Input.GetAxisRaw(“Horizontal”); If that does show anything, your Input settings need to be changed to make sure it is picking up your mouse movements.
2. Character Controller
Make sure you have a character controller component attached to the object. The coding won’t work if it is referencing the character controller, but it doesn’t exist on your game object.
controller.Move(movement);
In the Update function that actually tells it to move, make sure that the “movement” variable is actually updating with your input values. It should be something along those lines.
Hello and thank you for a great approach to 3rd person movement controller :) I am very new to Unity scripting, but have experience scripting in other packages, and I was wondering how could I modify the script so that if I press “backwards” key (or negative vertical) that CharacterController doesn’t rotate, but actually moves backwards?
Thanks!
Howdy,
Thanks for the tutorial. I have gone through a couple times with a few projects. I keep getting this error:
Assets/NewBehaviourScript.js(21,13): BCE0005: Unknown identifier: ‘targetDirection’.
Not really sure why its telling me this is an unknown identifier.
Any more help would be GREATLY appreciated.
Thanks
-Richard
Where is the “targetDirection” variable created. The program doesn’t think that it exists. If that variable exists in another script, you need to make sure that you add a reference to it so that it will exist in other scripts.
YOU GAVE US A FIVE STAR TUTORIAL HERE. Just wondering How do I get my left stick on my PC Xbox controller to control the camera?
SORRY I MEANT RIGHT STICK…YOU GAVE US A FIVE STAR TUTORIAL HERE. Just wondering How do I get my right stick on my PC Xbox controller to control the camera?
How can I get the x box stick on the right side to move camera around character
I wondered is there any way to make the character go faster/turn slower? I can’t figure it out >_>
Heya,
Thanks for this! This tutorial was very helpful, I’ve been trying to get away from the Prefab thirdperson control system for a while now :)
Super helpful!