• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
Question by Leyren · Mar 28, 2016 at 12:28 AM · rotationscript.vector3floataccuracy

Accuracy issues with Float (Vector3)

Hi.

I wrote an NPC movement script, which includes the rotation of the NPC-character in order to make it look forwards after changing its direction. It works like follows: After the movement to a certain point, it the NPC turns around until the correct rotation is reached, and then starts moving.

The problem is that it sometimes get stuck at rotating. Obviously this is caused by the floating point inaccuracy. I checked that by printing the result of the == opertion where I compare the normalized vectors, and it returns false. I also printed the values of the vectors to see how big the inaccuracy is:

(0.9831, 0.0000, 0.1830) (0.9824, 0.0000, 0.1866)

I know that the == operator has approximation integrated, so I am quite astonished that this simple rotation already causes problems.

Are there any ways to prevent this (globally or in that special case). I honestly don't even know if the script does a good job, I started with unity a few days ago. Any advice would be appreciated.

Edit: Here the complete code. Nothing is accessed by other scripts.

 [RequireComponent(typeof(Animator))]
 public class Patrol : MonoBehaviour {
     public Transform[] patrolPoints;
     private Transform current;
     private int currentPoint = 0;
     public float moveSpeed;
     public float animSpeed = 1.5f;
     private Animator anim;
 
     [Range(0,360)]
     public float rotationSpeed;
 
     void Start () {
         transform.position = patrolPoints[currentPoint].position;
         current = patrolPoints[currentPoint];
         anim = gameObject.GetComponent<Animator>();
         anim.speed = animSpeed;
         anim.SetFloat("Speed", moveSpeed);
     }
 
     private bool rotating = false;
     void Update() {
         if (equals(transform.position,current.position))
         {
             currentPoint = (currentPoint + 1) % patrolPoints.Length;
             current = patrolPoints[currentPoint];
             rotating = true;
         }
 
         if (!rotating)
         {
             transform.position = Vector3.MoveTowards(transform.position, current.position, moveSpeed * Time.deltaTime);
         }
         else {
             Vector3 targetDir = current.position- transform.position ;
             transform.rotation = Quaternion.LookRotation(Vector3.RotateTowards(
                transform.forward, 
                targetDir, rotationSpeed*Time.deltaTime, 0));
             if (equals(targetDir.normalized, transform.forward.normalized))
             {
                 rotating = false;
             }
         }
     }

 
Comment

People who like this

0 Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image elenzil · Mar 31, 2016 at 07:09 PM 0
Share

you're saying that modifying the transform.forward value is also modifying the transform.position ? that does seem weird. can you make a minimal repro of that ?

for what it's worth, i often use a utility function of my own: bool isWithinEpsilon(float a, float b, float epsilon = 0.0001f) { float diff = b - a; return ((-epsilon < b) && (b < epsilon)); }

2 Replies

· Add your reply
  • Sort: 
avatar image

Answer by Zeoli · Mar 28, 2016 at 06:19 AM

I believe you may need to mess around with this Mathf function. http://docs.unity3d.com/ScriptReference/Mathf.Approximately.html

Comment
taxvi
Leyren

People who like this

2 Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Leyren · Mar 31, 2016 at 06:16 PM 0
Share

I didn't know about the Approximately-function, thanks. But that is not enough. Comparing (0.9832, 0.0000, 0.1827), (0.9824, 0.0000, 0.1866) returns false for the z-values, which are 0.0039 apart. I guess I have to compare it manually then?

avatar image Cherno Leyren · Mar 31, 2016 at 06:43 PM 0
Share

You can also try using the Math.Round method (using System). Note that it's not Math*f*.Round. Math.Round accepts an int parameter to pass the desired number of decimal places that should be rounded to.

avatar image

Answer by phxvyper · Mar 31, 2016 at 07:20 PM

You've been misinformed. The == operator is an equality operator and does not have any checks for approximation. This is why Mathf.Approximately exists.

Personally, I believe there's something in your code for rotation or movement that you can change in order to fix this issue. However, what you can do is create your own form of Approximately, like I do on occasion:

 public bool Approximately(float a, float b, float epsilon)
 {
     return (Mathf.Abs(a - b) < epsilon) || (Mathf.Approximately(Mathf.Abs(a - b), epsilon));
 }
 
 //or JS:
 
 function Approximately(a : float, b : float, epsilon : float) : float
 {
     return (Mathf.Abs(a - b) < epsilon) || (Mathf.Approximately(Mathf.Abs(a - b), epsilon));
 }

epsilon is the maximum distance between two floats that you'll accept as approximately.

 Approximately(0.05f, 0.1f, 0.05f) //will return true
 Approximately(0.06f, 0.1f, 0.04f) //will return true
 Approximately(0.05f, 0.1f, 0.06f) //will return false

Comment
Leyren

People who like this

1 Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bunny83 · Mar 31, 2016 at 08:06 PM 1
Share

Actually the Vector3 equality operator does some approximation. It's implemented like this:

 public static bool operator ==(Vector3 lhs, Vector3 rhs)
 {
     return Vector3.SqrMagnitude(lhs - rhs) < 9.99999944E-11f;
 }

The question was about comparing Vector3 values, not float values. However the error is way beyond most approximation limits. When dealing with vectors you never really compare two vectors directly. You usually check the distance between them against an epsilon value.

When using SqrMagnitude keep in mind to square the epsilon as well. So if the distance between the vectors should be lower than 0.01f you have to compare against (0.01f² == 0.0001f). SqrMagnitude is a bit faster to calculate than magnitude as it doesn't require a square root.

avatar image phxvyper Bunny83 · Apr 01, 2016 at 05:21 AM 0
Share

Oh i thought he was talking about directly comparing floats, not Vectors. Whoops!

avatar image Leyren · Apr 01, 2016 at 05:12 AM 0
Share

Personally, I believe there's something in your code for rotation or movement that you can change in order to fix this issue.

I edited the post and provided the full code, perhaps you can find something.

avatar image phxvyper Leyren · Apr 01, 2016 at 05:23 AM 1
Share

Have you tried Slerp'ing the rotation instead of using RotateTowards?

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

7 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How can I replace this Vector3 with a float? 2 Answers

Rotating a character along the x and z-axis to align with a vector3 direction. 1 Answer

LookAt To Only Rotate on Y Axis 2 Answers

maximum distance from origin (float precision) 1 Answer

Rifle Accuracy w/ Rotation 3 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges