This site uses strictly necessary cookies. More Information

X- Home /

# Limit local rotation

Hi,

i have an issue i am not able to resolve myself. I have looked around topics here, but i couldnt find exactly what i am looking for.

I have an object, which is rotating around its axis, i.e. its orbiting on place. But i need to limit the rotation when it stops. So it means the object can have local y rotation anything between 0 and 360. Lets say its current y rotation is 100. I need to limit in +/- 40 interval. I.e. 60 - 140. Thats not problem, i am clamping it using eulerAngle.y. But when the current rotation is for example 20, then the issue comes up as it the interval is -20 to 60. Which causes issues as the rotation is only 0 - 360. So when the current rotation gets to this break point, whole limit code brakes and it does some funky stuff. Is there anyway how to prevent it from going in 0-360 interval and have negative values for rotation ? Or any other solution ?

Thanks a lot for any reply.

Luke

This is really just a coding question, so you should post your code.

Hi! 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 `$$anonymous$$athf.Clamp(angle, min, max)`

and you're done. Have a nice day!

**Answer** by aldonaletto
·
Jul 11, 2011 at 04:50 AM

This is really a big problem: the limits below 0 and above 360 can't become negative or higher than 360; to further complicate matters, if you rotate the object past 359, it returns to 0; if you rotate the object below 0, it returns to 359. But I created a function similar to Mathf.Clamp which I think may solve your problem:

```
function ClampAngle(angle: float, min: float, max: float): float {
if (angle<90 || angle>270){ // if angle in the critic region...
if (angle>180) angle -= 360; // convert all angles to -180..+180
if (max>180) max -= 360;
if (min>180) min -= 360;
}
angle = Mathf.Clamp(angle, min, max);
if (angle<0) angle += 360; // if angle negative, convert to 0..360
return angle;
}
```

This function has some limitations: it uses Mathf.Clamp if **angle** is in the range 90 to 270, and convert everything to the -180..+180 when **angle** is outside this range. In any case, the result is converted to 0..360 (the range *eulerAngles* accepts).

You can use it this way:

```
transform.eulerAngles = Vector3(0, ClampAngle(angle, ang0-40, ang0+40), 0);
```

Please notice that this function has a "capture" range: if the parameter **angle** is between -90 and +90 degrees around the center of the range, it will be clamped correctly; if its out of this range, the function may "think" it is at the "other side" of the circle, and clamp to the wrong limit - for example: if the range is centered at 120 degrees, an angle lower than 270 will be clamped to 160 degrees, but above 270 it will be clamped to 80 degrees. This will not be a problem if you're clamping the angle returned by *eulerAngles* after a small rotation (what seems to be your case), since it will not be too away from the range. If you want to clamp an arbitrary angle to the limits, however, this problem may arise.

Iam having small rotation, so its not problem. I have tested it very intensly and it works very smoothly withouth any issue so far. So thanks a lot again :).

I was trying to do something similar, but for clamping an arbitrary angle to the limits, so the problem that aldonaletto mentioned in his comment occurred. I started a new question thread about it here: http://answers.unity3d.com/questions/226639/limit-local-rotation-around-x-y-and-z-axes-when-ro.html

I saw this been looking for ages for something good. This is absolutely brilliant work thanks very much

**Answer** by mkgame
·
Apr 19, 2016 at 11:22 PM

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!

mkgame. Seeing your code, i think you don't need to check for negative values after calling NormalizeAngle.

**Answer** by immerhart
·
Oct 19, 2012 at 07:07 PM

its a little late, but here my approach:

```
m_startRotation = transform.rotation.eulerAngles.y;
m_minRot = m_startRotation - 90.0f;
m_maxRot = m_startRotation + 90.0f;
m_isTranslationNessecary = false;
// check if rotation happens between 0/360
if(m_minRot <= 0.0f)
m_minRot += 360.0f;
if(m_maxRot >= 360.0f)
m_maxRot -= 360.0f;
if(m_minRot > m_maxRot)
m_isTranslationNessecary = true;
```

and this function checks if the obj can be rotated:

```
private float ClampAngle(float angle, float min, float max, bool isTranslationNecessary)
{
if(!isTranslationNecessary)
{
if(angle < min )
return min;
if(angle > max)
return max;
}
else
{
if(angle > max && angle < min)
{
if(min - angle > angle - max)
return max;
else
return min;
}
}
return angle;
}
```

**Answer** by VictorPinto90
·
Jun 13, 2015 at 04:13 PM

Here is my solution. I have a camera thar rotates around a target in X and Y axis. I'm only limiting the angle in X-Axis

```
public void OnDrag (PointerEventData eventData){
float deltaX = Mathf.Clamp(eventData.delta.x,-maxPointerDelta,maxPointerDelta)*Time.smoothDeltaTime*speed;
float deltaY = Mathf.Clamp(eventData.delta.y,-maxPointerDelta,maxPointerDelta)*Time.smoothDeltaTime*speed;
Vector3 relativePos = cameraTransform.position - handler.position;
Vector3 v1 = new Vector3(relativePos.x,0,relativePos.z);
float angleX = Vector3.Angle(v1,relativePos);
float futureangle = angleX + -deltaY;
if(futureangle<maxAngle && futureangle>minAngle){
cameraTransform.RotateAround(target.position,cameraTransform.right,-deltaY);
}
cameraTransform.RotateAround(targer.position,Vector3.up,deltaX);
}
```

**Answer** by rblkwa
·
Nov 22, 2016 at 02:38 PM

```
public void SetRotation(float amount) {
float clampedAngle = Mathf.Clamp(CheckAngle(transform.eulerAngles.x - amount), -15, 15);
transform.eulerAngles = new Vector3(clampedAngle, transform.eulerAngles.y, transform.eulerAngles.z);
}
public float CheckAngle(float value)
{
float angle = value - 180;
if (angle > 0)
return angle - 180;
return angle + 180;
}
```

### Your answer

### Welcome to Unity Answers

The best place to ask and answer questions about development with Unity.

To help users navigate the site we have posted a site navigation guide.

If you are a new user to Unity Answers, check out our FAQ for more information.

Make sure to check out our Knowledge Base for commonly asked Unity questions.

If you are a moderator, see our Moderator Guidelines page.

We are making improvements to UA, see the list of changes.

### Follow this Question

### Related Questions

Limit local Rotations on one axis 3 Answers

rotate slowly! 1 Answer

Head and body rotate threshold 1 Answer

Limiting Local Turret Rotation 0 Answers