• 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
0
Question by Nimwe · Apr 29, 2018 at 03:10 PM · if-statementsbounds

If not executing code even though its instruction results clearly in TRUE

I'm losing my mind over some piece of code which should supposedly execute but doesn't even though the debug.log clearly shows it should.

I have, in my project, a collection of surfaces of some walls in a map (parallelepipeds) which I detached from their walls by a constant - cameraHeight - which are held into a Bounds[].

Now i'm trying to generate random points in space and to take the closest point on these surfaces and check whether it is in free space or contained by other bounds.

To do so, I'm also using a bool function which should return true if and only if the closest projection on these surfaces is at a good distance from the other walls (at least cameraToWallMinDistance) and at the right distance from the closest wall (cameraHeight). The problem is it only ever returns true if I'm asking for a point projected on the floor, and doesn't work if the closest surface is on any of the other walls.

 private bool IsAtDistanceFromWalls(Vector3 coordinates) 
             {
                 bool ret = false;
                 Vector3 closestPoint;
 
                 //first check if the point is at the wanted distance from walls
                 //check the ceiling
                 closestPoint = ceilingTransform.gameObject.GetComponent<Collider>().ClosestPointOnBounds(coordinates);
                 if (Vector3.Distance(coordinates, closestPoint) == cameraHeight)
                 {
                     ret = true; Debug.Log("I became true on ceiling");
                 }
                 else Debug.Log("I didn't become true on ceiling because the distance between me and c was " + Vector3.Distance(coordinates, closestPoint) + " while camera needs to be at " + cameraHeight);
                 //check the floor
                 closestPoint = floorTransform.gameObject.GetComponent<Collider>().ClosestPointOnBounds(coordinates);
                 if (Vector3.Distance(coordinates, closestPoint) == cameraHeight)
                 {
                     ret = true; Debug.Log("I became true on floor");
                 }
                 //check the walls
                 for (int i = 0; i < wallTransforms.Length; i++)
                 {
                     closestPoint = wallTransforms[i].gameObject.GetComponent<Collider>().ClosestPointOnBounds(coordinates);
                     if (Vector3.Distance(coordinates, closestPoint) == cameraHeight)
                     {
                         ret = true; Debug.Log("I became true on wall" + (i+1));
                     }
                     else Debug.Log("I didn't become true on wall " + (i+1) + " because the distance between me and wall was " + Vector3.Distance(coordinates, closestPoint) + " while camera needs to be at " + cameraHeight);
                 }
 
                 //then check if the closest point is more than the minimum
                 closestPoint = ceilingTransform.gameObject.GetComponent<Collider>().ClosestPointOnBounds(coordinates);
                 if (Vector3.Distance(coordinates, closestPoint) < cameraToWallMinDistance)
                 {
                     ret = false; Debug.Log("I became false on ceiling");
                 }
                 //check the floor
                 closestPoint = floorTransform.gameObject.GetComponent<Collider>().ClosestPointOnBounds(coordinates);
                 if (Vector3.Distance(coordinates, closestPoint) < cameraToWallMinDistance)
                 {
                     ret = false; Debug.Log("I became false on floor");
                 }
                 //check the walls
                 for (int i = 0; i < wallTransforms.Length; i++)
                 {
                     closestPoint = wallTransforms[i].gameObject.GetComponent<Collider>().ClosestPointOnBounds(coordinates);
                     if (Vector3.Distance(coordinates, closestPoint) < cameraToWallMinDistance)
                     {
                         ret = false; Debug.Log("I became false on wall" + (i + 1));
                     }
                 }
                 Debug.Log("*****************************" + ret);
                 return ret;
             }

You'll notice I have a lot of debug.Logs in there. Here comes the funny part. The if (Vector3.Distance(coordinates, closestPoint) == cameraHeight) instruction gets executed ONLY if the bound is that of the floor, even though the debug.log shows two identical values for cameraHeight and Distance (there fore the aforementioned instruction is true).

What is going on? What dumb thing am I forgetting?

Proof of what I'm saying about the if statement: alt text alt text

alt text

Comment
Add comment
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

1 Reply

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by Bunny83 · Apr 29, 2018 at 04:31 PM

You do realise that the floating point numbers you're printing here are implicitly rounded to 1 decimal place? The actual values are most likely not the same. In almost all cases you never want to compare two floating point values for equality. If they are 0.000001 off they are not equal. Try a Log statement like:

 Debug.Log("I didn't become true on wall " + (i+1) + " because the distance between me and wall was " + Vector3.Distance(coordinates, closestPoint).ToString("F10") + " while camera needs to be at " + cameraHeight.ToString("F10"));

and you will see that the numbers are not equal. In most cases you want to check for a small range. The easiest way is to do something like this:

 // get delta
 float delta = Vector3.Distance(coordinates, closestPoint) - cameraHeight;
 
 // check if the value is +-0.1 around 0
 if (Mathf.Abs(delta) < 0.1f)
Comment
Add comment · 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 Nimwe · Apr 29, 2018 at 07:37 PM 0
Share

Yes! Although it actually happened that in a few cases the output was "I didn't become true on wall i+1 because the distance between me and wall was 0.200000000 while camera needs to be at 0.200000000".

I'm guessing the precision is much higher on floats? Also I'm not really sure how these numbers got changed this way - my guess is that the rounding from Vector3.Distance is messing things up because cameraHeight was simply defined as 0.2f and the Distance from any wall was incremented through normalToTheSurface*cameraHeight. The only way this can happen is if the Vector3.Distance messes things up, basically...

avatar image Bunny83 Nimwe · Apr 30, 2018 at 02:44 AM 0
Share

You do realise that the value "0.2" actually can't be represented exactly by a float. A float uses power of two fracions. That are 0.5, 0.25, 0.125, 0.0625, ... That actual number is stored in scientific format as binary number. "0.2" in decimal is actually:

 // as binary number
 1.10011001100110011001101 * 10^-11
 // as decimal number with power of two exponent
 1.600000023841858 * 2^-3
 // actual decimal number
 0.20000000298023223876953125

The next smaller number would be

 0.199999988079071044921875

You may want to have a look at this nice IEEE 754 converter (I've actually made an editor window for Unity ^^)


I also highly suggest you watch this computerphile video on floating point numbers

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

82 People are following this question.

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

Related Questions

How to Bind Maximum Rotation Values 0 Answers

Tips on how to handle multiple if statemens 1 Answer

Ease in transform.LookAt() - keep other target within camera boundaries 1 Answer

Generate Bounding Box, In Game 1 Answer

Issue using separate GameObject to detect bounds 0 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