- Home /

# Having trouble checking my rotational values.

I'm trying to rotate an object and check when it's rotated a certain amount so it knows when to stop. I have a playable character that banks left while you hold down left, and banks right when you hold down right, but they need to stop once they bank about 10 degrees in either direction.

This is all pretty easy logically until you factor in that rotations "wrap around" and go from 360 back to 0, so now I'm a little confused about how to actually do this.

I was going to post my code, but none of it works the way I originally planned it, so any help would be greatly appreciated as I'm back to square one.

As a quick update to what I've tried, I also tried doing a simple check such as "if Z rotation is less than 10, increase, if greater than 350, decrease" but this again causes problems with the wrapping.

So, by bank, you mean a Z-rotation? When you bank, are you also turning that direction? Side-slipping (not changing Y-angle, but sliding a little sideways as you move forwards?) Bank+turn or move can drive you into the ground if you aren't careful.

Right, z-rotation. There's no other turning happening, just a z-rotation.

**Answer** by _MGB_
·
Apr 20, 2011 at 08:52 AM

Probably better to maintain a separate roll offset value in the player [-10 to +10] and then just set the roll with this value wrapped.

I suppose... I was mostly worried that somehow the variable and the actual rotation angle might get out of sync (somehow). I'll try doing something similar.

If you set the rotation to -10, then look it up, it might say 350, so DON'T LOO$$anonymous$$ IT UP. Code looks like: `if(Input.Get$$anonymous$$ey("a")) { zAng-=0.1; if(zAng<-10) zAng=-10; } transform.eulerAngles=Vector3(0,0,zAng);`

To "synch," only ever look at and change zAng, and set "real" rotation from it last.

**Answer** by synapsemassage
·
Apr 20, 2011 at 09:36 AM

Maybe this is a starting point for you? I haven't tested the code though.

```
public var maxRotationDelta : float = 10;
public var speed : float = 45.0;
private var initialAngleY : float;
private var bankLeft : boolean;
private var angleY : float;
```

```
```

function Start()
{
initialAngleY = transform.eulerAngles.y;
}
function Update () {

if(bankLeft)
{
maxRotationDelta = maxRotationDelta + 180;
}
angleY = Mathf.MoveTowardsAngle(transform.eulerAngles.y, initialAngleY + maxRotationDelta, speed * Time.deltaTime);
transform.eulerAngles = Vector3(0, angleY, 0);
}

Thanks for that. Didn't even know about $$anonymous$$oveTowardsAngle, might help in co$$anonymous$$g up with a solution. Once I do, I'll be sure to post what I did in my question.

**Answer** by hellcats
·
Apr 21, 2011 at 12:20 AM

You could just maintain a separate variable which is the amount of rotation you have added so far. Then just check this variable instead of transform.rotation.

This is better solved with a dot product, on normalized Vectors it represents a normalized range from -1, 0, 1 where -1 and 1 represent orthogonal and 0 represents parallel, so you will know when your rotation is close to 90 degrees by testing a dot product.

In a flight sim I made I used this to test if the plane was flying up or forward by its +Z axis as shown below:

Get degrees of plane in regards to horizon: Vector3.up is world up(sky) and transform.forward is jet's current direction.

float horizonAngle = Vector3.Dot( transform.forward, Vector3.up) * $$anonymous$$athf.PI/2 * $$anonymous$$athf.Rad2Deg;

Actually, I think you have that backwards: a Dot product of 1 means parallel, and 0 means orthogonal. (BTW: I'm making a flight sim too!)

**Answer** by TheDemiurge
·
Apr 24, 2011 at 11:12 AM

If there's no other rotation (and even if there is) this should be pretty simple. What works for me is using the input axes. Let's say you're using the "Horizontal" (A/D/Left/Right) keys:

```
var maxBankAngle: float = 10;
var bankInput: float = 0;
var tempZRot: float = 0;
var refTransform: Transform = transform;
```

```
```

function Update()
{
// store the axis' value in case we want it later
bankInput = Input.GetAxis("Horizontal"); // returns between -1 and 1
tempZRot = maxBankAngle * bankInput; // between -10 and 10
if (tempZRot < 0)
{
tempZRot += 360;
}
// using local angles will keep proper rotations if we're parented
refTransform.localEulerAngles.z = tempZRot;
}

By using the axis, you get 4 things:

1. a way of easily maxing out your rotation

2. have it reset without extra checks for key held/released

3. automatically turn the proper direction; if you find directions are opposite from what you need, simply change +/- somewhere in that equation

4. **(bonus!)** you get to play with the sensitivity / gravity values on the axis (see documentation on Input), to adjust how fast we reach this maximum bank degree or recover from it

**Answer** by Wolfram
·
Apr 26, 2011 at 09:21 AM

We solved this problem in the past by converting both the upper and lower limit, as well as the current angle, into a defined "clamping space" (e.g., 0<=limitRight<=360 and limitLeft<=limitRight). Using this method, we can supply our limits as an *arbitrary* number (e.g., even way outside the 0..360 interval), and it will still be interpreted correctly.
One of the main advantages is, that you can define any interval without twisting your brain thinking about wrap-around problems. For example, limitLeft=-10 and limitRight=10 maps to -10..10, but so does 350..10, or even -370..-350. On the other hand, it is also possible to map to the inverse interval: limitLeft=10 and limitRight=-10 maps to 10..350, and therefore allows *only* values >10 and <-10, and omits the range -10..10.

Furthermore, we added additional checks to a) correctly initialize the angle to the nearest border if it is outside the given interval, and b) if the current angle is set outside the allowed interval externally (e.g., by editing it directly in the Inspector), limit the interaction to one direction, the direction towards the nearest limit border (hard to explain, try it for yourself).

(Note that it can happen for large rotSpeed and the special case of "almost-full" 360 intervals (for example, 1 to 360) that the change in angle between two frames is too large and it "jumps" over the interval that is outside the allowed range (0 to 1))

`using UnityEngine;`

```
```

public class LimitedRotation : MonoBehaviour {
// limitLeft is the minimal allowed angle
public float limitLeft = -10;

```
// limitRight is the maximal allowed angle
public float limitRight = 10;
// rotSpeed is a general scaling factor
public float rotSpeed = 200;
private bool haveLimits;
void Start(){
float newAngle=0;
// prepare rotation limit tests (left/right)
if(limitLeft==limitRight){
// unrestricted rotation
haveLimits=false;
}else{
haveLimits=true;
// make sure 0<=limitRight<=360 and limitRight-limitLeft=(0..360) (-360<=limitLeft<=360)
while(limitRight<0)
limitRight+=360;
while(limitRight-limitLeft>=360)
limitLeft+=360;
while(limitLeft>limitRight)
limitLeft-=360;
if(limitLeft>0){
// 0 is not in allowed interval; initialize the angle to the nearest valid boundary
float rightLimit=Mathf.Min(limitRight,360-limitRight);
float leftLimit=Mathf.Min(Mathf.Abs(limitLeft),360-Mathf.Abs(limitLeft));
if(leftLimit>rightLimit)
newAngle = limitRight;
else
newAngle = limitLeft;
}
}
transform.localEulerAngles=new Vector3(0,0,newAngle);
}
void Update(){
float deltaAngle=Input.GetAxis("Horizontal");
float oldAngle = transform.localEulerAngles.z;
float newAngle = oldAngle - rotSpeed * deltaAngle * Time.smoothDeltaTime;
if(haveLimits){
while(oldAngle>limitRight)
oldAngle-=360;
if(oldAngle>=limitLeft)
{
// clamp to limit
while(newAngle>limitRight)
newAngle-=360;
if(newAngle<limitLeft)
if(deltaAngle<0)
newAngle=limitRight; // rotate left limit
else
newAngle=limitLeft; // rotate right limit
}else{
// we are outside the limit
// so only allow movement towards nearest limit
float distToRight=Mathf.Abs(oldAngle-limitRight);
distToRight=Mathf.Min(Mathf.Abs(oldAngle-limitRight-360),distToRight);
distToRight=Mathf.Min(Mathf.Abs(oldAngle-limitRight+360),distToRight);
float distToLeft=Mathf.Abs(oldAngle-limitLeft);
distToLeft=Mathf.Min(Mathf.Abs(oldAngle-limitLeft-360),distToLeft);
distToLeft=Mathf.Min(Mathf.Abs(oldAngle-limitLeft+360),distToLeft);
if(deltaAngle<0 && distToLeft>distToRight ||
deltaAngle>0 && distToLeft<distToRight)
newAngle=oldAngle;
}
}
while(newAngle<0) newAngle+=360;
while(newAngle>360) newAngle-=360;
transform.localEulerAngles=new Vector3(0,0,newAngle);
}
```

}

(yes, all "while()..." commands can be optimized by using an appropriate %/multiplication/fraction computation, instead of a stupid loop)

Note, in the code above limitLeft/limitRight can only be adjusted to a certain amount on-the-fly, since the initialization is done in Start(). If you want to adjust the limits freely (e.g., via script etc.), you should move the that initialization from Start() to an Update() function.

### 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

Flip over an object (smooth transition) 3 Answers

freeze rigidbody of my player 1 Answer

How do i reflect a rotation 1 Answer

Sphere on cube floor doesn't rotate after too much delay 1 Answer