The following code is stable for all angles. Both methods can be static. NormalizeAngle method fix the angles above 360 and under -360 degree and the ClampAngle method normalize the angles from -180 to 180 to make the angles clamp-able. You can call this method with e.g. ClampAngle(angle, 3450, -70), ClampAngle(angle, -70, 70), ClampAngle(angle, -470, 5604). Its stable! I used this code to limit the angles of my hover vehicle, to avoid turning around it.
/** Normalize angles to a range from -180 to 180 an then clamp the angle
* with min and max.
*/
protected float ClampAngle(float angle, float min, float max) {
angle = NormalizeAngle(angle);
if (angle > 180) {
angle -= 360;
} else if (angle < -180) {
angle += 360;
}
min = NormalizeAngle(min);
if (min > 180) {
min -= 360;
} else if (min < -180) {
min += 360;
}
max = NormalizeAngle(max);
if (max > 180) {
max -= 360;
} else if (max < -180) {
max += 360;
}
// Aim is, convert angles to -180 until 180.
return Mathf.Clamp(angle, min, max);
}
/** If angles over 360 or under 360 degree, then normalize them.
*/
protected float NormalizeAngle(float angle) {
while (angle > 360)
angle -= 360;
while (angle < 0)
angle += 360;
return angle;
}
Use it in your code to limit the angles:
transform.eulerAngles = new Vector3(0, ClampAngle(angle, -40, 40), 0);
Or like this for fake tilt to terrain normal:
// Raycat down to terrain, in my case the GameManager.TERRAIN_MASK is
// the terrain mask.
Vector3 linecastTo = new Vector3(transform.position.x, transform.position.y - 100, transform.position.z);
Vector3 linecastFrom = new Vector3(transform.position.x, transform.position.y + 20, transform.position.z);
bool hitSomewhat = Physics.Linecast(linecastFrom, linecastTo, out hitInfo, GameManager.TERRAIN_MASK);
float SwingSpeed = 1;
// Difference between our up vector and the terrain normal vector.
Quaternion tilt = Quaternion.FromToRotation(transform.up, hitInfo.normal);
Vector3 rot = transform.eulerAngles;
// Rotation for the next frame until this value ClampAngle(tilt.eulerAngles.x, -30, 30)
// has been achieved. Max tilt is 30, even on a 45 degree terrain mesh normal!
Quaternion qRot = Quaternion.Euler(
Mathf.LerpAngle(rot.x, ClampAngle(tilt.eulerAngles.x, -30, 30),
Time.deltaTime * SwingSpeed),
rot.y,
Mathf.LerpAngle(rot.z, ClampAngle(tilt.eulerAngles.z, -30, 30),
Time.deltaTime * SwingSpeed));
// RB is the rigidbody, smooth physical change because of the LerpAngle before.
RB.MoveRotation(qRot);
Happy coding!
This is really just a coding question, so you should post your code.
– WazHi! Good news everyone! I'm using Unity 5.3.4 and there's no need for any angle conversion or special clamping. Quaternion.Euler() takes care of it. And it understands negative angles. So you just say
– mikii123Mathf.Clamp(angle, min, max)and you're done. Have a nice day!