Unity Quaternions
Unity Quaternions
A tutorial which helps get your head from Eular Angles to Quaternions
By David Lancaster
Introduction
Hey Guys!
This is a tutorial for beginners to Unity, who either have no idea what a Quaternion is and how to use it, or are
struggling trying to get their brain from Eular Angles to Quaternions. Although this tutorial is a great introduction,
there are many intelligent forum users and threads that can provide much more valuable information than you
may find here. Regardless I hope this tutorial helps!
There are many ways to go about coding rotations, I have limited experience so there may be more efficient
ways to code than I have here. I am going to assume that you know some basic things about Unity's scripting
language. The transform object and the various properties and functions it can use.
If you are new to scripting then it is very normal for information found in this tutorial to go over your head, just
remember, it's okay, you're not the only one who experiences it. If something doesn't make sense keep going
through the tutorial, post a thread on the forums asking for help, reread certain sections of the tutorial. And even
after you spend a lot of time trying to understand something and you still don't, it's okay, it happens to most of
us.
If you are used to using Vectors and Eular Angles, converting and using them to rotate an object in Unity can be
confusing at first. Especially if you are not aware how you can go about rotating vectors and converting vectors
to Quaternions.
There are many functions which link Vectors, Eular Angles and Quaternions to each other. The two types of
classes that we'll use shall be 'Quaternion' and 'Vector3'. Each contains functions to work with each other. Also,
the Transform object contains it's own set of good features you can use to help with rotations..
Why C Sharp?
Unfortunately I am much more familiar with C Sharp than I am with Java, I have found C Sharp to require more
syntax, however I do find it's structure more organized than Java. I shall attempt to explain the C Sharp syntax
throughout this tutorial as we come across it.
I have begun by creating a plane in the 'GameObject – Create Other' menu, named it Ground and scaled it's X
and Z components by 10. I also created a material in the project window by right clicking in the project window
and selecting 'create – material', I made the material a dark color and assigned the material to the Ground's
mesh renderer material. I then created a cube and named it Player, the reason I added this material to the
ground is so that the player isn't the same color as the ground.
(to rename an object in Unity, select it first, then click it and leave your mouse over it for a second or two, you
should then be able to rename the object)
Next we are going to create a new C Sharp script and name it 'PlayerScript' (right click in the project window).
Open up your script and change the classes name to the name of the script (this is very important and wont work
unless you do this):
using UnityEngine;
using System.Collections;
}
}
Now let's drag the script onto our player object in game.
The next step is to be able to access the camera from script, there are many ways to go about doing this
however for this tutorial we'll create a public variable GameObject, and we shall attach the camera to it.
A difference between C Sharp and Java is that when defining variables a type must be giving, in this case our
type is GameObject and the variable/pointer is named cameraObject. Let's go to our Unity window and drag our
MainCamera object (which should have automatically been created when you started a new unity project) onto
the cameraObject field which appears in the PlayerScript component of the Player object.
In C Sharp, all public variables declared inside the class, can be accessed and changed by external scripts, if
those other scripts have a pointer to this particular GameObject you can access it's attached script component
and the public variables within it. For example, any variables declared private, can only be accessed and
changed within that script. Anything declared public can be accessed from other scripts that you write in your
game. Anything declared public shall also appear in the script component in the Object's inspector window, as
we have seen with the variable cameraObject.
Here's where the bulk of our code comes in, it may seem overwhelming if you're new to this, don't worry I'm
going to explain the code in detail, go ahead and copy paste the code, don't run your game just yet, we want to
set some variables too:
public float cameraDistance; // the distance the camera should be placed from the player
public float cameraHeight; // how high the camera should be
private float cameraAngleToPlayer; // the current angle the camera is to the player
private Vector3 tempVector; // a temporary vector we shall use for calcuations
Firstly we have defined some new variables, cameraDistance is how far the camera will be placed from the
player, I have set it's value to 10 in my editor. Camera Height is how high to place the camera from the player,
set it to about 5. As these are public variables we can change them from the edtior. Our private variables, we
could have defined locally within the Update function however I choose to define them above. Go ahead and
run your game and use the arrow keys to move the camera.
Then if you wanted to convert assign a float's value to an integer you would do as follows:
integerVariable = (int)cameraDistance;
tempVector = Vector3.forward;
Vectors initally just contain a position, if not set it will contain 0,0,0, Vectors can contain positions with no
magnitude (direction, their direction is pointed towards null I would guess), or positions with magnitude. If you're
used to eular angles you'd probably be very comfortable and familiar with using Vectors as angles. In this
example I am giving a Vector a direction. I want the Vector to point forwards along the Z axis. Vector3.forward
is the same as typing Vector3(0,0,1); Now my vector has a direction rather than just being at a position.
Here we are simply changing a variable based on player input, by pressing right or left the variable will change,
this variable indicates the angle at which the camera shall be orbiting the player at.
Here is where we are actually rotating our Vector which once faced forward along the Z axis. To rotate a vector
in Unity you can rotate it by multiplying it with a Quaternion. There is a formula for doing this. For example
'Vector3 = Quaterion * Vector3' shall work but 'Vector3 = Vector3 * Quaternion' wont work as there is an order as
to how things must be done. As the numerical value of cameraAngleToPlayer changes so does the direction
which tempVector is pointing hence the camera orbits around the player as input is received.
In fact we didn't even need to add 'tempVector = Vector3.forward' and could have simply made the last line of
code as follows:
tempVector = Quaternion.AngleAxis(cameraAngleToPlayer, Vector3.up) * Vector3.forward;
We are multiplying a Vector by an angle, this in turn rotates the Vector. In this case we do not want the
Quaternion, we want the Vector. Quaternions are used for rotations however we are placing the camera at a
position which changes based on an angle, and positions are Vector3 types. If we weren't focused on the
position and were working with rotations instead, we would go straight ahead and just rotate the Quaternion
instead of the Vector3.
We are now directly setting the camera's position. Firstly we want to place it at the player's position, because
this is the player's script, 'transform.position' is the player's position. Next we want to add
'(tempVector.normalized * cameraDistance)' to the position. 'tempVector.normalized' gives the vector a
magnitude of 1, meaning that it is going to move the camera's position 1 unit along tempVector's direction and
we have the new direction of that vector because we multiplied it by a Quaternion. However we are also
multiplying tempVector.normalized by cameraDistance. This means that the camera will move along
tempVector's direction by the number of units specified in cameraDistance. If we set this at 10, then the camera
will be placed at a position 10 units along the vector 'tempVector'.
We are then moving the camera up along the Y (vertical) axis by adding 'new Vector3(0,cameraHeight,0);' If you
aren't used to C Sharp, there are certain circumstances that the syntax 'new' needs to be used otherwise you will
get an error, this has to do with memory management. I am not sure how to explain how or why this is needed,
a programming guru could. It is a difference between using Java and C Sharp.
So hopefully you understand how we are placing our camera relative to the player's position, based on an
angle.
Next part is making the camera look towards the player. We need to give the camera's rotation component a
Quaternion. A great function to use is LookRotation, which will convert the direction of a vector into a
Quaternion. In this case we simply subtract the camera's position from the player's position to get a vector from
the Camera to the Player, we can then convert the direction of this vector into a Quaternion and directly assign it
to our camera's rotation:
cameraObject.transform.rotation = Quaternion.LookRotation(transform.position -
cameraObject.transform.position);
So that's it! The very beginning stages of learning how to become familiar with Quaternions from Eular Angles.
Another function to look into is 'Vector3.RotateTowards', using it you can interpolate a vector's direction to
another vector's direction. For example, if you know the position of an object you desire to rotate towards. Find
the vector from the object you wish to look at to your own transform position, and rotate towards it from your
current position:
And your object will rotate smoothly towards it's target (hopefully, unless my code is slightly off)
-David
www.youtube.com/daveriser
www.rebelplanetcreations.com