# How to clamp rotation, following Unity's quaternion rules

I want to clamp my camera’s pitch (rotation around its x-axis), and nearly every forum post or Unity Answers page says to use this method:

`````` 1. Grab the Euler angle for the angle to be clamped.
2. Clamp using Math.Clamp().
3. Assign the new angle to the rotation.
``````

However, this method is precisely what Unity advises not to do in their Quaternion and Euler Rotation article.

After some more searching, I found another answer that points to Unity’s own MouseLook.cs script in the Standard Assets. This script uses the following function (full code in the link):

``````Quaternion ClampRotationAroundXAxis(Quaternion q)
{
q.x /= q.w;
q.y /= q.w;
q.z /= q.w;
q.w = 1.0f;

float angleX = 2.0f * Mathf.Rad2Deg * Mathf.Atan (q.x);
angleX = Mathf.Clamp (angleX, MinimumX, MaximumX);
q.x = Mathf.Tan (0.5f * Mathf.Deg2Rad * angleX);

return q;
}
``````

I’ve implemented this method in my own code, with a slight alteration explained in the comments in the code.

``````public void Rotate(Vector3 input)
{
// The camera's pitch (xRotation) should be done about its own x-axis (Space.Self),
// but its pan (yRotation) should be down about the world's y-axis (Space.World).
// In order to accomplish this, I need to rotate the camera twice, isolating the x- and y-rotations.
Vector3 xRotation = new Vector3(input.x, 0, 0);
Vector3 yRotation = new Vector3(0, input.y, 0);
transform.Rotate(xRotation, Space.Self);
transform.Rotate(yRotation, Space.World);

// Clamp the xRotation amount - Bad way
//Vector3 currentRotation = transform.rotation.eulerAngles;
//currentRotation.x = Mathf.Clamp(currentRotation.x, pitchMin, pitchMax);
//transform.rotation = Quaternion.Euler(currentRotation);

// Clamp the xRotation amount - Good way
transform.rotation = ClampRotationAroundXAxis(transform.rotation);
}

// This method is taken in full from Unity's MouseLook.cs class in the Standard Assets.
private Quaternion ClampRotationAroundXAxis(Quaternion q)
{
q.x /= q.w;
q.y /= q.w;
q.z /= q.w;
q.w = 1.0f;

float angleX = 2.0f * Mathf.Rad2Deg * Mathf.Atan(q.x);
angleX = Mathf.Clamp(angleX, pitchMin, pitchMax);
q.x = Mathf.Tan(0.5f * Mathf.Deg2Rad * angleX);

return q;
}
``````

However, an odd behavior occurs when I try to rotate the camera beyond the clamp: the camera begins to roll about its z-axis. (GIF included below.) What’s going on here, and how do I fix it? Is it caused by my two-rotation solution?

The best answer I found is this: