0
\$\begingroup\$

I'm facing problem of the operations on rotations. I have a wheel with a start rotation of (0, 0, 0). The player has to rotate wheel 270 degrees in Y axis either left or right.

During the rotation slider should indicate progress of the rotation. For example if player rotated 135 degrees in right direction, slider is 50% filled to the right.

The thing is that I'm not sure how to get the value of which the player rotate the object. For example when I start rotating right my angle changes from (0, 0, 0) to (0, 359, 0). How can I resolve this issue so it knows that change from (0, 0, 0) to (0, 359, 0) means player rotated only +1 degree?

Problem illustration

\$\endgroup\$
4
  • \$\begingroup\$ Have a look at Vector3.Angle and Quaternion.Angle. \$\endgroup\$
    – schneebuzz
    Commented Feb 24, 2021 at 10:09
  • \$\begingroup\$ @schneebuzz thanks for the idea. I tried to test it, Quaternion.Angle seems to return nice values. Is there any way to get singed angle so I know whether player rotated left or right? \$\endgroup\$
    – Ardoos
    Commented Feb 24, 2021 at 11:10
  • \$\begingroup\$ A simple solution (which may or may not be possible) is to simply force the user to rotate it by doing something like rotateWheel(-5) or rotateWheel(5) instead of just directly setting the wheel's rotational value to the user's input. This would allow you to see where the wheel was, where it is moving to, as well as what direction it's moving (and how fast) without having to do extra calculations and predictions to try and get it right. Although that may not be an option. \$\endgroup\$ Commented Feb 24, 2021 at 12:02
  • \$\begingroup\$ Did you try Mathf.DeltaAngle? \$\endgroup\$
    – DMGregory
    Commented Feb 24, 2021 at 13:10

1 Answer 1

0
\$\begingroup\$

We can keep track of how many quarter-turns we've travelled, counter-clockwise from the start angle (this can go negative for clockwise turns). Then we can measure our current angle relative to the last quarter-turn milestone we crossed.

Because that milestone is never more than 90 degrees away from our angle last frame, we can move just shy of 90 degrees further in a single step and still unambiguously find the total rotation travel.

Then we can update the number of quarter-turns if we've crossed into a new quadrant.

public Transform wheel;   

public float totalAngle;

float _startAngle;
int _quarterTurns = 0;

void Start() {
    _startAngle = wheel.eulerAngles.z;
}

void Update() {
    float currentAngle = wheel.eulerAngles.z;

    // Compute the total angle at the last milestone.
    float milestoneAngle = _startAngle + _quarterTurns * 90;

    // Get the shortest signed difference from the last milestone (-180 to 180)
    float fromMilestone = Mathf.DeltaAngle(milestoneAngle, currentAngle);

    // Our total angle is the sum of the last milestone and our deviation from it.
    totalAngle = milestoneAngle + fromMilestone;

    // If we've crossed another 90-degree increment, update our milestone for next frame.
    if (Mathf.Abs(fromMilestone) >= 90) {
        _quarterTurns += Mathf.RoundToInt(fromMilestone)/90;
    }
}
\$\endgroup\$
1
  • \$\begingroup\$ Thanks, Mathf.DeltaAngle is what I was looking for. Milestones idea is perfect. \$\endgroup\$
    – Ardoos
    Commented Feb 25, 2021 at 7:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .