Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Applying rotation to transform does not have the same outcome

Discussion in 'Editor & General Support' started by Daniiii, May 6, 2021.

  1. Daniiii

    Daniiii

    Joined:
    Nov 13, 2013
    Posts:
    24
    I've come across some behaviour with applying a rotation to a transform that I don't really understand.

    What happens is: when I apply a rotation to a transform, the resulting rotation of this transform will sometimes not be the same that I applied.

    e.g.:
    Code (CSharp):
    1. var rotation = Random.rotation;
    2. transform.rotation = rotation;
    3. bool equals = transform.rotation.Equals(rotation);
    I noticed that when I normalize the rotation before setting it, it is equal more often (1/10 chance of it being not equal).
    My current guess is that Unity normalizes the Rotation every time it is set and with some Quaternions normalizing a normalized Quaternion will not give the same result?

    What I want to achieve is to take the rotation from an object, save it and later apply this rotation to the same object again so it is exactly the same.
    e.g.:
    Code (CSharp):
    1. var rotation = Random.rotation;
    2.  
    3. transform.rotation = rotation;
    4. rotation = transform.rotation;
    5. transform.rotation = rotation;
    6.  
    7. bool equals = transform.rotation.Equals(rotation); //should be equal, but it's not
    We're developing a game with cloning and we got deterministic physics somewhat figured out, except for this rotation thing that happens sometimes.

    Does anybody know what the cause of this is or how we could work around it?
     
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,722
    The cause of this problem is that
    transform.rotation
    is a calculated value. Every time you store it and recalculate it it is subject to floating point precision errors. The true rotation value of the Transform is stored in
    transform.localRotation
    . Try storing and restoring that instead. (naturally its global orientation is then also subject to the orientation of its parent.)

    That being said, simply storing and restoring the
    rotation
    should be very close to what it was previously and probably good enough for most use cases.
     
  3. Daniiii

    Daniiii

    Joined:
    Nov 13, 2013
    Posts:
    24
    Thank you, that makes sense.

    Sadly when I get and set localRotation instead of rotation it is also not equal every time.
     
  4. Lurking-Ninja

    Lurking-Ninja

    Joined:
    Jan 20, 2015
    Posts:
    9,907
    Even the
    1f == 10f / 10f
    doesn't resolve to true every time...

    Try
    Mathf.Approximately
    . Floating point errors accumulate and they will be ever so slightly different. Approximately takes this into account, so they will be deemed equal if the difference is or less than EPSILON.

    https://docs.unity3d.com/ScriptReference/Mathf.Approximately.html