Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

float is NaN?

Discussion in 'Scripting' started by TPEUnity, Sep 29, 2019.

  1. TPEUnity

    TPEUnity

    Joined:
    Jan 17, 2018
    Posts:
    36
    Why does this sometimes throws NaN to animator resulting in breaking my blend tree completely and not updating value with Animator.SetFloat() after it happens; ?

    Its attached to object that looks at a target by slerping. I havent been able to reproduce this constantly, only by randomly moving the target.


    Debug.Log doesnt seem to throw any obscure values (should be -1f, 1f or 0 as i only care about y-axis on this case).



    Code (CSharp):
    1.         public void SomeMethod()
    2.         {
    3.             Quaternion travel = transform.rotation * Quaternion.Inverse(previousRot);
    4.  
    5.             Vector3 axis;
    6.             float angle;
    7.             travel.ToAngleAxis(out angle, out axis);
    8.  
    9.             animator.SetFloat("AxisBetween", axis.y, 0.5f, Time.deltaTime);
    10.  
    11.             previousRot = transform.rotation;
    12.         }
     
    Last edited: Sep 29, 2019
  2. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    Presumable the problem is with
    axis.y
    on line 9?

    If so, then reading backwards, that comes, via line 7, from
    travel
    that is set on line 3. That, in turn, is calculated from
    previousRot
    . Have you checked for any scenarios where
    previousRot
    may be null or otherwise invalid?
     
  3. TPEUnity

    TPEUnity

    Joined:
    Jan 17, 2018
    Posts:
    36
    I still wasnt able to pin point the actual issue but as workaround i added NaN check where i just set axis.y to 0. Since its only for a frame i didnt notice any jitter in the blend tree i use it for.

    Code (CSharp):
    1.             if (float.IsNaN(axis.y))
    2.             {
    3.                 axis.y = 0;
    4.             }
    Also kinda weird Animator allows such value that it breaks the layer (or the float value since layer is pretty much locomotion blend tree.), others override layers still worked fine just not the one with blend tree.
     
  4. Doug_B

    Doug_B

    Joined:
    Jun 4, 2017
    Posts:
    1,596
    If that suffices, then great and glad you got it working.

    However, and I mention this only for completeness, I would make this observation: this is a sticking plaster that merely sidesteps a problem. So on the one hand, this change is possibly fine (dependant upon the actual cause in and of itself- you may find it comes back to bite). On the other, if this was a 'proper production' system, you would not want to accept or entertain code of that nature.

    So it's a case of horses for courses. :)
     
  5. JoshuaMcKenzie

    JoshuaMcKenzie

    Joined:
    Jun 20, 2015
    Posts:
    916
    I think the issue can happen when previousRot.forward == Vector3.back. its looking in completely the opposite direction from Quaternion.Identity and calling an inverse on a rotation is basically asking for a rotation back to the Identity along the shortest possible path. Since in this case, an infinite number of paths are the shorest path of rotation back to identity an axis of rotation cannot be determined. I'm willing to bet that if you debug.logged out the angle when the error happens it'd likely say 180 (or NAN depending on how it maths it out).

    Run a dot product on previousRot and Quaternion.Identity and if the value is super close to -1, you likely need to put in a failsafe for it.
     
  6. TPEUnity

    TPEUnity

    Joined:
    Jan 17, 2018
    Posts:
    36
    OK after some patient debugging i have solved it i think? What i think was the problem is when start == end the axis will result in infinities (animator doesnt like infinity :D ). So what i did i added this piece of code. Im not 100% this is the correct math, when it comes to quaternions im kinda just winging it... I no longer was able to produce the issue and i didnt see anything wrong about the behavior.

    I used this website as help if someone is interested (and maybe correct me?)
    http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/

    Code (CSharp):
    1.        
    2.             if (angle < 0.001f)
    3.             {
    4.                 axis.x = 0f;
    5.                 axis.y = 0f;
    6.                 axis.z = 0f;
    7.             }
    8.             else
    9.             {
    10.                 axis.Normalize();
    11.             }