I got an issue when I’m trying to add gridpos to a custom 3D Hex grid.
I’m trying to add gridpos depending on transform.position and because it’s a hex then the positions.z value is 0.865f difference bewteen the gridpos.
int z = 0;
float zF;
if (map.GetChild(i).transform.position.z > 0)
{
zF = (map.GetChild(i).transform.position.z / 0.865f);
Debug.Log(zF + " int " + (int)zF);
z = (int)zF;
}
z = 0 for the first row.
It works fine until row 6 (z should be 5). the position.z is = 4.325f.
The debug tells me zF = 5 but (int)zF = 4.
How is it that zF can be 5 but (int)zF is 4? And what can I do to fix this issue?
At first I tried
z = (int)(map.GetChild(i).transform.position.z / 0.865f);
But that didn’t work so i changed it to the code above to try with first calculating the float (zF) and then convert it to int (z). But that didn’t work either, and now I’m currently out of ideas.
This is a classic floating point problem. I have a blog post about this to explain in more detail, but in short, math on CPUs with floating point numbers is very slightly imprecise. You are probably dividing 4.325f / 0.865f and getting a result of something like 4.99999999. This number is functionally identical to 5 for nearly all purposes, but when converting to int, anything after the decimal point is truncated, and you get 4.
Unity has a function Mathf.RoundToInt for this sort of issue.
When the number of significant digits of a float goes beyond 7 digits, converting the float to a string will round the output, and if all of the fractional digits are rounded up then it will display an integral value even though there actually are a lot of fractional digits. The number of significant digits a string can display goes up to 9 if you use the “G9” format specifier, which is necessary for proper serialization. A float is capable of representing a vast number of significant digits, as far as the binary value stored in memory is concerned. So, there are many floating-point values that float.ToString(), which includes the debugger in Visual Studio, literally cannot display accurately.