- Home /
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:
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)
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...
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
Follow this Question
Related Questions
How to Bind Maximum Rotation Values 0 Answers
Can you find the length or “bounds” of an edge collider2D using Bounds? 0 Answers
Is there a way to check for a line as opposed to a Vector3 point with Bounds.Contains? 1 Answer
Collider2d.bounds.Intersects not detecting intersection 1 Answer
Distance sensor 1 Answer