U
15 / 22 · 11 min
FAQ

Rotation: Euler angles, Quaternions, and which one you may touch

the short answer

How do I rotate an object, and what is a Quaternion?

Use Quaternion.Euler(x, y, z) when you know the angle you want, and Quaternion.LookRotation with RotateTowards or Slerp to turn towards something. Never add to transform.rotation directly: it holds four numbers that are not angles, and writing angles into it produces nonsense.

Position and scale are three numbers you can add to. Rotation looks like three numbers in the Inspector and is not, and every beginner discovers this the same way: copy transform.rotation into a variable, add 1 to its y, write it back, and watch the object do something indescribable. (C# will not even accept transform.rotation.y += 1 on one line — the property hands you a copy.)

What the Inspector shows you is not what is stored

Unity stores rotation as a Quaternion: four numbers, x, y, z and w, which together describe one axis and one amount of turn around it. None of the four is an angle in degrees. The Inspector converts them into three friendly Euler angles for display, and converts your typing back the other way.

Setting a rotation you already know

Quaternion.Euler — degrees in, Quaternion out
// Face 90° to the right, level, no roll.
transform.rotation = Quaternion.Euler(0f, 90f, 0f);

// Local rotation instead: relative to the parent, not to the world.
transform.localRotation = Quaternion.Euler(0f, 90f, 0f);

// Add 90° to whatever it is now. Quaternions multiply, they do not add.
transform.rotation *= Quaternion.Euler(0f, 90f, 0f);

Turning towards something

This is the case that actually comes up: an enemy should face the player, a turret should track a target, a character should turn the way it is walking. It is two steps — work out the rotation you want, then move towards it a bit each frame.

FaceTarget.cs
using UnityEngine;

public class FaceTarget : MonoBehaviour
{
    public Transform target;
    public float turnSpeed = 360f;   // degrees per second

    void Update()
    {
        if (target == null) return;

        Vector3 to = target.position - transform.position;

        // Flatten it, or the enemy tips forward to look down at a short player.
        to.y = 0f;

        // LookRotation complains about a zero vector: standing exactly on the target.
        if (to.sqrMagnitude < 0.0001f) return;

        Quaternion wanted = Quaternion.LookRotation(to);
        transform.rotation = Quaternion.RotateTowards(
            transform.rotation, wanted, turnSpeed * Time.deltaTime);
    }
}

RotateTowards or Slerp?

  • RotateTowards turns at a fixed number of degrees per second and arrives. Use it when the speed of the turn is part of the design — a turret that cannot snap around instantly.

  • Slerp slows down as it closes in, never quite arrives, and its speed depends on how far it has to go. Use it for a camera or anything that should feel soft rather than mechanical.

  • A Slerp written as Slerp(a, b, speed * Time.deltaTime) is frame-rate dependent. The fix is the same as for position: 1f - Mathf.Exp(-speed * Time.deltaTime).

Spinning something continuously

transform.Rotate — the one case where you do not touch rotation directly
// Around its own up axis: a coin spinning on the spot.
transform.Rotate(Vector3.up * 90f * Time.deltaTime, Space.Self);

// Around the world's up axis: orbiting behaviour, unaffected by tilt.
transform.Rotate(Vector3.up * 90f * Time.deltaTime, Space.World);

Gimbal lock, and why you keep your own angle

Euler angles describe a rotation as three turns applied one after another. When the middle turn reaches 90°, the first and third end up spinning around the same axis, and one degree of freedom disappears. This is gimbal lock, and in practice it is what makes a first-person camera go haywire when you look straight up.

The pattern that avoids all of it: keep the angle yourself
using UnityEngine;

public class MouseLook : MonoBehaviour
{
    public float sensitivity = 2f;

    // Your own numbers, in degrees, never read back from the transform.
    float yaw, pitch;

    void Update()
    {
        yaw   += Input.GetAxis("Mouse X") * sensitivity;
        pitch -= Input.GetAxis("Mouse Y") * sensitivity;

        // Clamping works because pitch is a plain float you control.
        pitch = Mathf.Clamp(pitch, -80f, 80f);

        transform.rotation = Quaternion.Euler(pitch, yaw, 0f);
    }
}

the lesson that builds this

Third-person orbit

This post is a standalone recipe. In the course, the same thing is built as part of the one project that runs through all five tabs — Camera & Input, lesson 02.