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

Question Fixing floating point errors on an angle float

Discussion in 'Scripting' started by tetriser016, Jan 26, 2021.

  1. tetriser016

    tetriser016

    Joined:
    Jan 3, 2014
    Posts:
    100
    When I was working on my game (which heavily relies on direct rotations), I ran into some problems with how I can overcome the floating point errors when rotating objects.

    The way my game works is simple: use the arrow to change the stage's rotation to match with the arrow's direction (which is down). I used iTween for the rotation system.

    So how can I remedy the floating point errors without compromising the mechanics of my game? I've attached the stripped-down version of my project so you can understand how my game supposedly works.
     

    Attached Files:

  2. Adrian

    Adrian

    Joined:
    Apr 5, 2008
    Posts:
    1,061
    I don't have time to dive into a full project. If possible, try to post stripped down code snippets instead of a full project. Not many users here will download and import a full project to answer a question, security concerns notwithstanding.

    Generally, you don't use equality with floating point numbers. Instead, you check if the difference between two floats is below a given threshold. What a sensible threshold is depends on the use case.

    Comparing rotations, you can use Mathf.DeltaAngle, Vector3.Angle or Quaternion.Angle to get the difference between two angles/directions and then check if it's smaller than a few degrees or maybe a fraction of a degree, depending on how accurate you need it to be.
     
    GroZZleR likes this.
  3. tetriser016

    tetriser016

    Joined:
    Jan 3, 2014
    Posts:
    100
    Oh wait, I think I mistook my problem.
    I actually want to detect if the angle is a valid float value (not 90.0001 or 1-something, then serve the value into my rotator script.

    This is how I check and send the rotation:
    Code (CSharp):
    1. if (collision.gameObject.GetComponent<RotationArrow>())
    2.         {
    3.             RotationArrow ra = collision.gameObject.GetComponent<RotationArrow>();
    4.             //Debug.Log(Mathf.Abs(ra.gameObject.transform.eulerAngles.z));
    5.  
    6.             if (Mathf.Approximately(ra.gameObject.transform.eulerAngles.z, 0))
    7.             {
    8.             }
    9.  
    10.             else
    11.             {lockdown += lockdownAmount;
    12.                 arrowPos = ra.transform;
    13.                 sr.RotateStage(-Mathf.RoundToInt(ra.transform.eulerAngles.z));
    14.             }
    15.         }
    And this is where the value was sent to:
    Code (CSharp):
    1. public void RotateStage(int rt)
    2.     {
    3.         if(cooldown == 0 && rt != 0)
    4.         {
    5.             float rrt = rt;
    6.             //Debug.Log(rt);
    7.             iTween.RotateTo(gameObject, iTween.Hash("z", transform.eulerAngles.z + rrt, "easeType", "linear", "time", rotateTime));
    8.             cooldown = 20;
    9.         }
    10.     }
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,520
    Don't rely on the angles you get back form eulerAngles. In fact you should never read from them: those angles are just for "niceities," whereas inside a Quaternion is actually a matrix of four floats completely unrelated to axis angles.

    Instead, keep your own notion of rotation, then "drive" the rotated object to that position.

    Code (csharp):
    1. private float currentAngle;
    2. private float desiredAngle;
    Then have your tween drive currentAngle towards desiredAngle:

    Smoothing movement between discrete values:

    https://forum.unity.com/threads/beginner-need-help-with-smoothdamp.988959/#post-6430100

    The code: https://pastebin.com/ePnwWqnM

    To "drive" the actual rotation:

    Code (csharp):
    1. MyPiece.transform.rotation = Quaternion.Euler( 0, 0, currentAngle);
     
  5. tetriser016

    tetriser016

    Joined:
    Jan 3, 2014
    Posts:
    100
    I'm pretty new to this, how can I use this with my scripts?
    Also how can I fix the errors on the children's rotations if it happened after the rotation?
     
    Last edited: Jan 28, 2021