Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rotation of Object Unity rotating at wrong value

My problem is I want to be able to rotate a cylinder 9 times. 360/9 is 40 so I all I should need to do is rotate by 40 degrees 9 times. This doesn’t work however as when I rotate the cylinder for the first time instead of by 40 degrees it rotates by 39.99 degrees. This happens at other rotations as well.

I’m rotating by doing this.

if(Input.GetKeyUp("i"))
      transform.GetChild(m_Section).Rotate(0,40.0f,0);

I have unity version 3.4 it is not pro and I’m coding in C#.

Any help appreciated as I have just started trying to learn unity.

like image 398
Dave Avatar asked Dec 10 '11 18:12

Dave


1 Answers

Unity3D stores rotations in a pretty abstract mathematical representation called quaternion. Tranformation from and to Euler angles (what you see in Unity editor) involves a cascade of trigonometric functions and thus is prone to rounding errors especially for the simple float type.

To get around this problem in your case I recommend storing the initial Quaternion object before starting to rotate and set it at the end of the process. Some pseudo-code:

public class RotationController : MonoBehaviour {
    Quaternion rotationAtStart;
    int numOfRotations = 0;

    void rotate () {
        numOfRotations++;
        if (numOfRotations == 1) {
            rotationAtStart = transform.rotation;
        } else if (numOfRotations < 9) {
            transform.Rotate (new Vector3 (0,40.0f,0));
        } else if (numOfRotations == 9) {
            transform.rotation = rotationAtStart;
        }
    }
    void Update () {
        if (numOfRotations < 9) {
            rotate ();
        }
    }
 }   

The special situation of 360° makes this approach stable. For less than 360° you have to live with small rounding errors. For this case I would recommend calculating the target quaternion Quaternion.RotateTowards and set it in the last step analog to the 360 case.

Another useful thing for you are Animations. You can define an animation as smooth or in discrete steps and just call GameObject.animation.Play("MyRotation") if "i" is pressed. Use an AnimationEvent at the end to get informed when the animation is terminated.

And at last Mathf contains a function Approximately that deals with the problem of floating point imprecision.

like image 60
Kay Avatar answered Oct 10 '22 09:10

Kay