The question is answered, right answer was accepted
Don't trust "Vector3.Distance"?
I'm not sure if image is uploaded, in case it's not, here what it contains:
current distance = 15.76397
UnityEngine.Debug:Log(Object)
previous distance = 15.0685
UnityEngine.Debug:Log(Object)
current position = X:9.795947; Z:23.43502;
UnityEngine.Debug:Log(Object)
previous position = X:9.832729; Z:23.4193;
UnityEngine.Debug:Log(Object)
[must be equal] current destination = X:-4.699924; Z:29.62956;
UnityEngine.Debug:Log(Object)
[must be equal] previous destination = X:-4.699924; Z:29.62956;
UnityEngine.Debug:Log(Object)
So, the problem is... it's not truth, the previous distance was 15.8039657202238, not 15.0685, and I'm 100% sure it has nothing to do with floating precision thing, the difference is huge.
the formula is square((x2-x1)^2 + (y2-y1)^2), current distance calculated properly: 15.76396529621405, however previous distance is wrong.
This happens very very rarely, but still happens. So how exactly Vector3.Distance works? Should I make my own method with that formula and use it instead?
And here's the code (not related stuff was removed and comments added):
void FixedUpdate ()
{
if (OnFixedUpdate == true && ShipBool[0] == true)
{
float f0 = Vector3.Distance (transform.position, ShipVector3);
if (ShipBool[1] == false && f0 > ShipFloat[0] + ShipFloat[4])
{
Debug.Log ("current distance = " + f0);
Debug.Log ("previous distance = " + ShipFloat[0]);
Debug.Log ("current position = X:" + transform.position.x + "; Z:" + transform.position.z + ";");
Debug.Log ("previous position = X:" + TestVector3[0].x + "; Z:" + TestVector3[0].z + ";");
Debug.Log ("[must be equal] current destination = X:" + ShipVector3.x + "; Z:" + ShipVector3.z + ";");
Debug.Log ("[must be equal] previous destination = X:" + TestVector3[1].x + "; Z:" + TestVector3[1].z + ";"); //just to be 100% sure that ShipVector3 doesn't magically change somehow (it doesn't)
Debug.Break (); //needed to instantly pause the game when this rare bug happens, so i can check everything in editor and later reconstruct it by placing 1 ship at previous position, 2nd ship at current position, 3rd ship at ShipVector3 and ensure that everything 100% fine from my side
<not related code>
}
else if (f0 < ShipFloat[4])
{
<not related code>
}
else if (f0 < ShipFloat[0])
{
ShipFloat[0] = f0; //ShipFloat[0] stores previous distance
}
TestVector3[0] = new Vector3 (transform.position.x, 0f, transform.position.z); //stores previous position
TestVector3[1] = new Vector3 (ShipVector3.x, 0f, ShipVector3.z); //stores the same non-changing ShipVector3 to be 100% sure it's really non-changing
if (ShipBool[1] == true)
{
<not related code>
}
}
}
Edit: Forgot to mention, Y is always 0 everywhere, objects move in "2d space" in 3d, so it not the cause of the problem, plus I was checking it when the game paused and sure about it.
Edit#2: So I changed this:
//float f0 = Vector3.Distance (transform.position, ShipVector3);
float f0 = Mathf.Sqrt ((transform.position.x - ShipVector3.x) * (transform.position.x - ShipVector3.x) + (transform.position.z - ShipVector3.z) * (transform.position.z - ShipVector3.z));
Tested it for a long-long time and bug won't occur any longer. So the problem was in Vector3.Distance after all.
Or, in other words I replaced every Vector3.Distance in my project with this:
public float Vector3Distance2D (Vector3 V30, Vector3 V31)
{
return Mathf.Sqrt ((V30.x - V31.x) * (V30.x - V31.x) + (V30.z - V31.z) * (V30.z - V31.z));
}
Answer by ForUnityAccount · Aug 28, 2018 at 06:36 AM
Actually I lied, I was simply very unlucky, after more testing it actually occurred again.
Can someone tell me how to fix this and make sure the REAL distance is always calculated?
Edit: I'm 100% sure it's not floating error, because what really happens here is: you subtract an-always-positive number from another number (ship moves in a straight line and never goes back) and then, somehow, magically, that number becomes BIGGER! How is this possible? The only possible way (the reason why this check exists at first place) is if your ship is fast and moved beyond destination, that's why I need this check, but this happens way BEFORE that and happens randomly.
It's the same as if you add always positive number to your another number and then it somehow becomes lower. This is logically impossible. Float can never become lower by adding something to it regardless of precision.
Edit: JVene's answer solved the problem.
It's late, so I'm not 100% clear, but I think your 'previous' distance (shipfloat[0]) isn't being updated every time it is supposed to do so, and you're not getting the correct previous distance in your debug output. I don't think the 'else' should apply for the previous distance update.
Yes, it seems you were right, at least ~4 $$anonymous$$utes of testing on many-many-many ships at the same time and no bug yet. Will need some more testing (it's very rare bug).
Edit: Even more testing and no bug, don't know why, but this solved the problem, I would mark your answer ac accepted, but it's comment.
Glad that helped. In 30+ years I've never seen a computer fail at math, especially randomly, except for that P90 bug back in the 90's.
For the first 5 or so years, though, I would SWEAR that the computer had failed to get the right answer, or just ignore some "if" statement, or simply didn't do what was clearly written. I mean, bet all my cash on it!
if it's bigger, then debug stuff will happen, if it's equal... then no need to update, if it's less, then it updates ShipFloat[4] can be ignored, I even removed it later, but ok, I'll try removing if-check
Oh and according to Debug.Log it's updated anyway.
Running this testing code does never print a single debug.Log:
for (int i = 0; i < 1000000; i++)
{
var v1 = new Vector3(Random.Range(-20000f, 20000f), 0, Random.Range(-20000f, 20000f));
var v2 = new Vector3(Random.Range(-20000f, 20000f), 0, Random.Range(-20000f, 20000f));
var d1 = Vector3.Distance(v1, v2);
var d = v2 - v1;
var d2 = $$anonymous$$athf.Sqrt(d.x * d.x + d.y * d.y + d.z * d.z);
if (d1 != d2)
{
Debug.Log("Dist1: " + d1.ToString("F10"));
Debug.Log("Dist2: " + d1.ToString("F10"));
}
}
So all your test cases are pretty pointless since you clearly have something wrong. It's suspicious that you store the current position in TestVector at the end but you compare it the next frame at the start. Note i've also run this test with a smaller random range but i get the same consistent behaviour.