Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • 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 /
  • Help Room /
avatar image
0
Question by AlienNova · Jul 10, 2016 at 04:44 PM · c#vectordotproduct

Vector2.Dot not returning 0

I have this bit of code here which uses Vector2.Dot to find out whether or not a hunter is behind it's prey.

         Vector2 preyWorldDir = prey.transform.TransformDirection (Vector3.left);
         Vector2 huntToPreyDir = transform.position - prey.transform.position;
 
         /*Dot Product*/
         if (Vector2.Dot (preyWorldDir, huntToPreyDir) < 0)
             print ("< 0");//Hunter is behind prey
         else if (Vector2.Dot (preyWorldDir, huntToPreyDir) > 0)
             print ("> 0");//Hunter is in front of prey
         else
             print ("= 0");//Hunter is perpendicular of prey

It does it job with finding out whether the hunter is behind/in front of the prey. But not when it's perpendicular. Vector2.Dot never returns 0 when the prey is facing 90 degrees away from the hunter. I can work around this, but it's really just bugging me and I have a feeling this will cause issues in the future.

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

2 Replies

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

Answer by Eno-Khaon · Jul 10, 2016 at 05:20 PM

Welcome to the wonderful world of floating point inaccuracy!

Zero happens to be an extremely unlikely number to see in a floating point variable. This is because the closer the number gets to 0, the closer it can be to 0.

What does that mean?

Floating point numbers are stored in a form similar to scientific notation. This combines (something like) an integer with a power-of-10 exponent. To give an example of this:

Let's use 7823846 as our base value. Then, let's turn that into a very large and a very small number, such as 7.823846e10 and 7.823846e-7, or 78238460000 and 0.0000007823846 respectively.

If you increased the base integer value by 1 at this point, you would see a change of 1000 or 0.0000000000001 respectively. There is a limit on how long the base value can be, 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 can reach 0, it is extremely unlikely when paired with slight inaccuracy of floating point numbers. For instance, if you've ever seen something like 0.999999999 instead of 1, 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 0 and it becomes less and less likely that the floating point value will accurately calculate a result of 0.

This is why Unity has a simple, convenient workaround 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");
Comment
Add comment · Show 5 · 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 AlienNova · Jul 10, 2016 at 05:52 PM 0
Share

That was extremely helpful, but it's still not returning perpendicular. differenceDot ends up being 1.192093E-07, which the hunter then takes as "$$anonymous$$ove 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 ($$anonymous$$athf.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
             $$anonymous$$ove (prey.transform.position, 0.16f);//0.16f is just how close the hunter will get to the prey before it stop moving
avatar image Eno-Khaon AlienNova · Jul 10, 2016 at 06:09 PM 0
Share

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 -1 to 1. If both vectors had a length of 2, however, the output would range from -4 to 4 because their components are being multiplied together. Likewise, the values can also wind up being very small very easily.

avatar image AlienNova · Jul 10, 2016 at 06:02 PM 0
Share

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.

avatar image AlienNova AlienNova · Jul 10, 2016 at 06:05 PM 0
Share

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.

avatar image Bunny83 · Jul 10, 2016 at 06:33 PM 0
Share

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 $$anonymous$$athf.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.

avatar image
1

Answer by Bunny83 · Jul 10, 2016 at 05:04 PM

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;

Comment
Add comment · Show 3 · 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 Bunny83 · Jul 10, 2016 at 05:06 PM 0
Share

ps: "0.9" equals about 25° so the area would be 50°

avatar image AlienNova · Jul 10, 2016 at 05:24 PM 0
Share

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.

avatar image Bunny83 AlienNova · Jul 10, 2016 at 06:07 PM 0
Share

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;

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.

Follow this Question

Answers Answers and Comments

172 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 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 avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Dynamic List update 0 Answers

Is Vector3.Dot faster than Vector3.Angle? 1 Answer

How to get and change RectTransform position (Left, Right, Top, Bottom) values through the script? (theres a screenshot) 2 Answers

[SOLVED]Unexpected results 0 Answers

Dot Product Help 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