Unity Rotation Note

Note on rotation in Unity.

Quaternion is used to represent rotations in Unity. It’s described by four properties x, y, z and w. However 99% of the time you are not suggested to directly change those values instead of using some useful functions provided by Quaternion.

Rotation VS LocalRotation

The rotation of the transform in world space stored as a Quaternion.

The rotation of the transform relative to the parent transform’s rotation.

It means that if the object has no parent(or let’s say parent is the world root), rotation and localRotation is same. However, if the object has a real parent, then the rotation is the combination of its localRotation and the parent’s rotation(not linear addition).

Transform.RotateAround

public void RotateAround(Vector3 point, Vector3 axis, float angle);

Rotates the transform about axis passing through point in world coordinates by angle degrees.
This modifies both the position and the rotation of the transform.

This is useful when we know the rotation point, axis and angle in world space.
And it’s more powerful than Transform.Rotate.
If we want to rotate around the parent, just put the parent’s position in point. (We don’t need to use localRotation)

Example: Rotate around a point in a constant rotation rate

1
2
3
void Update() {
transform.RotateAround(Vector3.zero, Vector3.up, 20f * Time.deltaTime);
}

Transform.Rotate

public void Rotate(Vector3 eulerAngles, Space relativeTo = Space.Self);

Applies a rotation of eulerAngles.z degrees around the z axis, eulerAngles.x degrees around the x axis, and eulerAngles.y degrees around the y axis (in that order).

If relativeTo is not specified or set to Space.Self the rotation is applied around the transform’s local axes. If relativeTo is set to Space.World the rotation is applied around the world x, y, z axes.

This is useful when we know the eulerAngles to rotate.

Example: Self Rotation

1
2
3
void Update() {
transform.Rotate(Vector3.up * Time.deltaTime);
}

Transform.LookAt

public void LookAt(Transform target, Vector3 worldUp = Vector3.up);

Rotates the transform so the forward vector points at /target/‘s current position.

Then it rotates the transform to point its up direction vector in the direction hinted at by the worldUp vector. If you leave out the worldUp parameter, the function will use the world y axis. worldUp is only a hint vector. The up vector of the rotation will only match the worldUp vector if the forward direction is perpendicular to worldUp.

This is useful to face the object towards a given direction.

Use Quaternion

Another way to rotate an object is directly setting the rotation/localRotation to a quaternion.

We don’t initianlize a quaternion by its constructor, instead we use the public static function of Quaternion.

Example: Rotate towards a quaternion (Linear)

1
2
3
4
void Update() {
float step = speed * Time.deltaTime;
transform.rotation = Quaternion.RotateTowards(transform.rotation, target.rotation, step);
}

We need to know the target’s rotation.

Example: Rotate towards a quaternion (Non-linear)

1
2
3
4
5
6
7
8
9
void Update () 
{
Vector3 relativePos = (target.position + new Vector3(0, 1.5f, 0)) - transform.position;
Quaternion rotation = Quaternion.LookRotation(relativePos);

Quaternion current = transform.localRotation;

transform.localRotation = Quaternion.Slerp(current, rotation, Time.deltaTime);
}

Example: Rotate towards a quaternion (Linear using interpolation)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void Update () 
{
Vector3 relativePos = (target.position + new Vector3(0, 1.5f, 0)) - transform.position;
Quaternion to = Quaternion.LookRotation(relativePos);

Quaternion from = transform.localRotation;

StartCoroutine(Rotate(from, to));
}

IEnumerator Rotate(Quaternion from, Quaternion to){
float t = Time.deltaTime;
Quaternion move = Quaternion.Slerp(from, to, t);
while(move != to){
transform.localRotation = move;

t += Time.deltaTime;
move = Quaternion.Slerp(from, to, t);

yield return null;
}
}