How do I count the revolutions of a float thats clamped from 0-360?

I have a float that adds up and subtracts based on user input. It turns the hand of a clock around 0-360 degrees. When we go around a second time the degree resets to 0. I want to figure out is how do I count how many times I’ve gone a full revolution around.
In the end Im trying to get a number that goes not from 0-360 but 0-Infinity.

Any help is appreciated. Thanks!

Division. Keep a second number that stores the value before it is modulo’d and divided it by 360 to get the revolutions.

1 Like

modulo is the ‘remainder’ of division

int divider (\ instead of /) is the ‘quotient’… although sadly this doesn’t exist in C#, but does in VB.Net of all places… (it’s inherited from DartmouthBASIC)

Of course you can always just get the quotient by truncating the result from float division (/): Math.Truncate(x / y)

The quotient of course being how many times you’d “gone around” when getting the modulo.

1 Like

Hmm, I think Modulo is probably the wrong word for my case. I’m simply counting how many times I go a full 0-360 around. @Ryiah how would you keep that second number? In a loop or if statement? Dividing by 360 will obviously represent one revolution but how do I count up from there with multiple revolutions without the number resetting each time?

Wait. Isn’t that what you’re trying to achieve? It might be easier to know what’s going on if we saw the code itself.

1 Like

I don’t really have any code but I’ll write out an example here;

If I turn the minute hand around multiple times it would be easy to divide by 360:
turn 0-360 = 1 revolution;
turn 360-720 = 2 revolutions;
turn 720-1080 = 3 revolution: etc;

The problem is the rotation input is clamped between 0-360; As I make a full rotation past 360 my rotation input goes back to 0 and increments from there.

Don’t clamp it to 0-360.

You instead keep the full raw value, and then you calculate the clamp and the revolutions from that as you need them.

public float angle;

public float AngleClamped
{
    get { return _angle % 360f; }
}

public float Revolutions
{
    get { return (float)System.Math.Truncate(angle / 360f); }
}

Noting that modulo probably isn’t the best here, because it doesn’t work in negative values the way you probably expect it to. And rather you should use a ‘wrap’ function. This is mine:

        public static float Wrap(float value, float max, float min)
        {
            max -= min;
            if (max == 0)
                return min;

            return value - max * (float)Math.Floor((value - min) / max);
        }

found here:

2 Likes

Im not clamping the rotation. I get the value from transform.rotation.eulerAngle.z; All I have to work with is the 0-360 rotation input. Therein lies my problem…

Just make an if that increments some value when you reach 359 or something

This works well to increment as I rotate past, but the ‘revolution’ int doesn’t go back down when rotating in reverse.

if(rotation < 350) {flag = false;}
if(rotation >= 350 && !flag) {revolution += 1; flag = true;}

stopping using the transform as the storage of the rotation.

Rather have your own variable… update it… and then copy that to the transform.

Separation of view and model.

2 Likes

Oh man, I didn’t think this would be so difficult. Thank you for your help so far.

I’m confused by this. The transform is the only input I have. I thought there maybe a simple for loop that could count the revolutions of the transform.rotation.z. I can’t seem to find anywhere else online that has tackled the problem. It seems relatively straight forward and I was hoping the amount of code talent here would have an easy solution. Maybe I’m looking at it wrong…

What is rotating the object?

1 Like

This is rotating my object. It works really well and includes velocity to add physics. Its in unity script.

#pragma strict
@Range(0, 20)
var mass : float;
var pos : Vector3;
var dragging : boolean;
var velocity : float;
private var previous : float;
 private var t : float;
var hit : RaycastHit;
var layerMask : LayerMask;
var col : Collider;

function Update(){ 

      pos = Camera.main.WorldToScreenPoint(transform.position);
      pos = Input.mousePosition - pos;

    if (Input.GetMouseButtonDown(0) && (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), hit, Mathf.Infinity,layerMask)) && col == hit.collider)         { previous = Mathf.Atan2(pos.y, pos.x) * Mathf.Rad2Deg; dragging = true;}
    if (Input.GetMouseButtonUp(0) )        {dragging = false;}


    if (dragging){t=0;    
        velocity = Mathf.Atan2(pos.y, pos.x) * Mathf.Rad2Deg  - previous; 
        previous = Mathf.Atan2(pos.y, pos.x) * Mathf.Rad2Deg;
        transform.localRotation.eulerAngles.z  += velocity;
}
     
    else{
    t += Time.fixedDeltaTime; 
      transform.localRotation.eulerAngles.z += Mathf.Lerp(velocity, 0 , Mathf.Exp(t)*mass);  
    }}

To get the 0-360 variable I use transform.rotation.eulerAngles.z to get the Quaternion rather than Euler which gets wonky by rotating only to 270 radians.

Instead of updating transform.localRotation.eulerAngles.z in that script you want to update the angle in the example code posted by @lordofduct earlier.

1 Like

I see…let me give it a shot.

You’ll have TWO variables. One that is already defined in the transform.rotation (the view) and one stored in your script (the model).

The ‘view’ isn’t used to store actual useful data. It instead is just there to give a display to what your underlying data is.

Your ‘model’ is what is the actual state information.

Your code updates your model (your custom variable like the source I showed earlier)… and then copies that to the view (the transform).

You never read state information from the view, because it’s considered volatile… it’s not actual data, it’s just the way we want the data to look. We always consult the model to know the actual state of the data.

This is useful for incase the ‘view’ ever changes on you. What if you decide to start making the ‘x’ axis the face, or maybe its some off weird axis like <1,1,1>. What if you change to 2d, or if you decide to display it digitally (like a digital clock). The view is independent of your data.

Furthermore, shape your data in a way that makes sense for your data, and transform it as necessary. Is this a clock? How about storing it as a ‘TimeSpan’ instead, and then copy out the seconds/minutes/etc as rotational values… degrees = seconds * 6, degrees = hours * 30… that sort of thing.

1 Like

Ok, the only input I have is as a euler which increments 0-270+90 to rotate around. I converted it to a Quaternion to get 0-360 rotation variable to simplify. This would be so easy if I didn’t have to go through a clamped rotation variable. I just don’t know how I can get linear float from the code I posted above…

I found this thread. It looks like I’m not the only person to have this issue. Workaround for Quaternion.eulerAngles 360 Degree Limit? - Questions & Answers - Unity Discussions

This guy claims he found a solution after adding an entire editor class. Ugh.