Mathf.Clamp not Working Properly

I want to clamp the vertical rotation of the first person controller I was making. I want to restrict the vertical rotation of the main camera between -90 and 90 degrees. The code is as follows:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MouseY : MonoBehaviour
{
[SerializeField]
private float _sensitivity = 5.0f;
private float _verticalInput;

// Update is called once per frame
void Update()
{
_verticalInput = Input.GetAxis("Mouse Y") * _sensitivity;
Vector3 lookDirectionY = transform.localEulerAngles;
lookDirectionY.x -= _verticalInput;
lookDirectionY.x = Mathf.Clamp(lookDirectionY.x, -90f, 90f);
transform.localEulerAngles = lookDirectionY;
}
}


In the above code, Mathf.Clamp does not work for -90. On reaching 0 degrees, it reels back to the +90 degrees. What could be the reason for this and how to resolve it?

• Angles can often mess up when you do simple "linear" clamp. - 90 drgrees is the same as 270 degrees, and that will be clamped to +90. Clamping angles is a bit more complex and often is done slightly differently depending on the setup and goal. Aug 23 '20 at 12:31
• I have tried to replace -90 with 270 and changing the min and Max value, but it gets messy. Aug 24 '20 at 2:47
• I meant that simply clamping between 2 values (no matter what they are) will never work for all kinds of angles. But I can't help you with an universal solution. It took me a lot of time to just come up with one that work for my requirements. Aug 24 '20 at 9:48
• Then what could be other different ways to approach the solution to this problem? Aug 24 '20 at 16:41
• I don't recommend trying to manipulate individual components of an Euler angle triplet - especially one that's been generated on demand from a source quaternion rather than constructed wholly in code you control and can reason about. They exhibit counter-intuitive wrap-around behaviour that makes lots of correct-looking code completely incorrect in practice. Working with direction vectors or quaternions might look more complex at first, but they give you much more reliable results because they don't have these wrap-around seams. Aug 24 '20 at 17:56

This example shows how you can convert any angle into the range -180 to 180.

Vector3 lookDirection = transform.localEulerAngles;
float x = lookDirection.x;
x -= _verticalInput;
//convert x into the range -180 to 180
x = x % 360;
if (x > 180) x -= 360;
else if (x < -180) x += 360;
//clamp and apply
x = Mathf.Clamp(x, -90f, 90f);
lookDirection.x = x;
transform.localEulerAngles = lookDirection;

• Note you can use Mathf.DeltaAngle(0, x) instead of writing the modulo/conditional branches yourself. But I'm not sure that solves the particular problem OP is having. Aug 24 '20 at 17:59