Comments and answers for "Vector2.Dot not returning 0"
http://answers.unity.com/questions/1214189/vector2dot-not-returning-0.html
The latest comments and answers for the question "Vector2.Dot not returning 0"Comment by Bunny83 on Bunny83's answer
http://answers.unity.com/comments/1214225/view.html
Actually the floating point precision has nothing to do with this problem. It's actually the other way round. The more precise the number representation is, the unlikely it is to get 0 as result. You can only get 0 if the vectors are indeed exactly 90° or due to rounding errors which is more likely the case. Using Mathf.Approximately actually **decreases** the accuracy by defining a small range which is considered "0".
There is almost no usecase where you want to know if two vectors are exactly perpendicular. So the problem is more a conceptual issue. You usually want to know if they are in a certain area / range. In most cases you want to split the full circle into 4 equal quadrants like i did in my second example.Sun, 10 Jul 2016 18:33:57 GMTBunny83Comment by Eno-Khaon on Eno-Khaon's comment
http://answers.unity.com/comments/1214219/view.html
Well, it makes perfect sense, actually, that the values would constantly change in general with any movement, but there's another reason entirely for that.
Vector length is a factor in the outcome of a dot product. For example, if you normalized both vectors, the output would range from <b>-1</b> to <b>1</b>. If both vectors had a length of 2, however, the output would range from <b>-4</b> to <b>4</b> because their components are being multiplied together. Likewise, the values can also wind up being very small very easily.Sun, 10 Jul 2016 18:09:42 GMTEno-KhaonComment by Bunny83 on Bunny83's comment
http://answers.unity.com/comments/1214218/view.html
Well you haven't normalized your "huntToPreyDir". So the result depends on the distance of the two objects:
Vector2 huntToPreyDir = transform.position - prey.transform.position;
huntToPreyDir.Normalize();
or
Vector2 huntToPreyDir = (transform.position - prey.transform.position).normalized;Sun, 10 Jul 2016 18:07:35 GMTBunny83Comment by AlienNova on AlienNova's comment
http://answers.unity.com/comments/1214217/view.html
I still have a problem I need to solve, but I feel like this answered the Vector2.Dot problem so there's no more reason to say my question wasn't answered.Sun, 10 Jul 2016 18:05:40 GMTAlienNovaComment by AlienNova on AlienNova's answer
http://answers.unity.com/comments/1214216/view.html
Just found out what's causing the such small amount of change. Even though the prey and hunter are on the same exact Y axis (0) the hunter for some reason rotates it self on the Z axis by 0.5729387.
Still have no idea why it does that.
Edit:
It puts it self on the Y axis of 0.009800009 for some reason when the game starts. Still leaves a mystery.Sun, 10 Jul 2016 18:02:32 GMTAlienNovaComment by AlienNova on AlienNova's answer
http://answers.unity.com/comments/1214215/view.html
That was extremely helpful, but it's still not returning perpendicular.
differenceDot ends up being 1.192093E-07, which the hunter then takes as "Move closer to prey" then drops down to -0.00999988 after the first update of moving, then differenceDot gradually gets smaller each update the hunter moves closer. Which I do not understand as it shouldn't since the vectors never change.
float d = Vector2.Dot (preyWorldDir, huntToPreyDir);
print (d);
if (Mathf.Approximately (d, 0.0f))
print ("Perpendicular");
else if (d > 0)
Strafe (Vector2.up, prey.transform.position);//Hunter strafes around prey to get behind it
else
Move (prey.transform.position, 0.16f);//0.16f is just how close the hunter will get to the prey before it stop movingSun, 10 Jul 2016 17:52:19 GMTAlienNovaComment by AlienNova on AlienNova's answer
http://answers.unity.com/comments/1214207/view.html
Just tried it, it returns perpendicular when it is. But also when it's not? Hard to explain, but I have the hunter strafing around the prey currently, telling when it's perpendicular to the prey or not and it's returning perpendicular when it's not.Sun, 10 Jul 2016 17:24:55 GMTAlienNovaAnswer by Eno-Khaon
http://answers.unity.com/answers/1214204/view.html
Welcome to the wonderful world of floating point inaccuracy!
<b>Zero</b> happens to be an <b>extremely</b> unlikely number to see in a floating point variable. This is because the closer the number gets to <b>0</b>, the closer it <i>can</i> be to <b>0</b>.
<i>What does that mean?</i>
Floating point numbers are stored in a form similar to scientific notation. This combines <sub><sup>(something like)</sup></sub> an integer with a power-of-10 exponent. To give an example of this:
Let's use <b>7823846</b> as our base value. Then, let's turn that into a very large and a very small number, such as <b>7.823846e10</b> and <b>7.823846e-7</b>, or <b>78238460000</b> and <b>0.0000007823846</b> respectively.
If you increased the base integer value by 1 at this point, you would see a change of <b>1000</b> or <b>0.0000000000001</b> respectively. <b>[There is a limit on how long the base value can be][1]</b>, as well as how far the decimal point can be placed along the number in either direction.
In short, what this means in this case is that while the number <b>can</b> reach <b>0</b>, it is extremely unlikely when paired with slight inaccuracy of floating point numbers. For instance, if you've ever seen something like <b>0.999999999</b> instead of <b>1</b>, it's basically indistinguishable in truth, but the number appears to be drastically different.
Well, this is the same sort of dilemma. You have near-infinite granularity available as you get closer to <b>0</b> and it becomes less and less likely that the floating point value will accurately calculate a result of <b>0</b>.
This is why Unity has a simple, convenient <b>[workaround][2]</b> to accommodate this accuracy issue for minute differences between numbers.
float differenceDot = Vector2.Dot (preyWorldDir, huntToPreyDir);
if(Mathf.Approximately(differenceDot, 0.0f))
print("= 0");
else if(differenceDot > 0)
print("> 0");
else// if(differenceDot < 0)
print("< 0");
[1]: https://en.wikipedia.org/wiki/Single-precision_floating-point_format
[2]: https://docs.unity3d.com/ScriptReference/Mathf.Approximately.htmlSun, 10 Jul 2016 17:20:11 GMTEno-KhaonComment by Bunny83 on Bunny83's answer
http://answers.unity.com/comments/1214198/view.html
ps: "0.9" equals about 25° so the area would be 50°Sun, 10 Jul 2016 17:06:15 GMTBunny83Answer by Bunny83
http://answers.unity.com/answers/1214197/view.html
It's almost impossible that Dot returns 0 since you work with floating point values. It only returns 0 when it's exactly 90°. If there is a small difference (0.000001) it won't return 0.
If you want to know when it's "about" 90° you might want to do this:
float d = Vector2.Dot (preyWorldDir, huntToPreyDir);
if (d < -0.9f)
print ("behind");//Hunter is behind prey
else if (d > 0.9)
print ("in front");//Hunter is in front of prey
else
print ("perpendicular");//Hunter is perpendicular of prey
If you want to split the area at the 45° angle into 4 quadrants you might want to use 0.7071 (cos(45°)). That way the "front" area has a size of 90° (+-45°) as well as the "back" area. Of course both sides also have that size.
if (d < -0.7071f)
print ("behind");//Hunter is behind prey
else if (d > 0.7071)
print ("in front");//Hunter is in front of prey
else
print ("perpendicular");//Hunter is perpendicular of prey
***edit***
I have missed that little detail about your code. As said in the comment below you haven't normalized your "huntToPreyDir" vector. If you don't work with normalized vectors the result of the dot product has a different meaning.
The dot product simply does this:
float Dot(Vector2 a, Vector2 b)
{
return a.x * b.x + a.y * b.y;
}
The nice property about the dot product is this relation:
Dot(a, b) = |a| * |b| * cos(angle);
or written in Unity C#_
a.magnitude * b.magnitude * Mathf.Cos(angle);
where angle is the angle between the two vectors.
If both vectors are normalized that means the length / magnitude of each vector is "1f" so the dot product simply returns the cos(angle) between the two vectors. This is what you want most the time.
If only one vector is normalized and the other isn't you actually project the length of the unnormalized vector onto the other vector.
If both vectors are not normalized the result of the dot product would be the area of the parallelogram with the two side length "a" and "b".
So you should normalize your vector like this:
Vector2 huntToPreyDir = (transform.position - prey.transform.position).normalized;Sun, 10 Jul 2016 17:04:26 GMTBunny83