Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 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 /
avatar image
4
Question by MountDoomTeam · Feb 07, 2013 at 09:37 PM · vector3efficiencycompareprecision

Vector3 == comparison efficiency and float precision

what is the error rate comparing Vector3's to be == ?

I seem to have about 20% of my objects missing when I compare to see if the objects are there, with : if (Vector3(X, Y, Z) == Vector3 (X, Y, Z)){ do something;}

I would prefer to compare them using integers/mathf.round, although there are many 1000ds compare, so I am concerned about speed. What is the the most efficient way to check many Vector3 == precisely?

here's a pic: if no tiles == expected terrain, make tile @ expected terrain... it's missing a line of tiles until spaceship position is updated.

alt text

missing tiles.jpg (483.5 kB)
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

5 Replies

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

Answer by aldonaletto · Feb 07, 2013 at 10:17 PM

Vector3 comparison must be based on distance: if the distance between two Vector3 is less than some predefined value, they are considered equal. This is exactly what Unity does when you compare two Vector3 (Vector3 == operator as implemented in Unity):

 public static bool operator ==(Vector3 lhs, Vector3 rhs)
 {
     return Vector3.SqrMagnitude(lhs - rhs) < 9.99999944E-11f;
 }

This function is called by Unity in the compiled code whenever you compare two Vector3 values, thus doing it yourself will not cause any loss in performance - for instance:

 public bool V3Equal(Vector3 a, Vector3 b){
     return Vector3.SqrMagnitude(a - b) < 0.0001;
 }

This limit is equal to 0.1mm, very small but still one million times greater than the builtin limit.

My fault! We're comparing squared magnitude, thus this limit equals 0.01 m, or 1 cm as noticed by @higekun in the comments (for 0.1 mm the value should be 0.00000001). For other limits, follow @Bunny83's suggestion (also posted in the comments).

In practice, you should replace the Vector3 equality operators by a call to this function, like this:

 if (posA == posB){ // < --- replace this...
     ...

 if (V3Equal(posA, posB)){ // < -- with this
     ...


 
Comment
Add comment · Show 4 · 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 MountDoomTeam · Feb 07, 2013 at 10:49 PM 0
Share

thanks everyone :)

avatar image higekun · Jan 08, 2014 at 02:57 PM 0
Share

Interesting to learn that this is what Unity does under the hood.

Worth noting: you're comparing squared magnitude, not magnitude, so the threshold is actually 1cm not 0.1mm - fairly coarse.

avatar image Bunny83 · Jan 08, 2014 at 03:17 PM 0
Share

@higekun: Well that's just basic math ;) The easiest way to define the threshold is to square the threshold manually. If you want 1 mm you just use (0.001 * 0.001) == 0.000001

avatar image aldonaletto · Jan 10, 2014 at 01:38 AM 0
Share

Thanks guys! I forgot that I was comparing squared distances.

avatar image
3

Answer by GerryM · Feb 07, 2013 at 09:52 PM

As the vector components are floats comparison for equality is kind of tricky. I'd use a helper function to test with some given precision. Something like:

 public static bool AlmostEqual(Vector3 v1, Vector3 v2, float precision)
 {
     bool equal = true;
         
     if (Mathf.Abs (v1.x - v2.x) > precision) equal = false;
     if (Mathf.Abs (v1.y - v2.y) > precision) equal = false;
     if (Mathf.Abs (v1.z - v2.z) > precision) equal = false;
         
     return equal;
 }

If that's too slow you can consider some optimization afterwards.

Comment
Add comment · Show 1 · 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 KaotikZ · Apr 01, 2020 at 11:45 AM 0
Share

better

public static bool AlmostEqual(Vector3 v1, Vector3 v2, float precision) { if ($$anonymous$$athf.Abs(v1.x - v2.x) > precision) return false; if ($$anonymous$$athf.Abs(v1.y - v2.y) > precision) return false; if ($$anonymous$$athf.Abs(v1.z - v2.z) > precision) return false; return true; }

avatar image
2

Answer by Dave-Carlile · Feb 07, 2013 at 09:56 PM

You can use the Mathf.Approximately function to test floating point values for "equality". You would have to test each vector component. Another method would be to subtract the two vectors and use Vector3.sqrMagnitude to test the length. That's potentially less efficient though.

The best way to check the performance is to write the code and check the performance.

Comment
Add comment · 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
2

Answer by marnsmith · Feb 07, 2013 at 11:40 PM

Floats are approximations, and all kinds of things can affect their actual value (release mode, platform, how they were derived)... so even if == sometimes works, it's generally not a good idea.

For vector comparisons, you can use something like this:

 float d = Vector3.SqrMagnitude(a - b);
 if (d > EPSILON) {
     // something amazing
 }

SqrMagnitude is faster than Magnitude since no square root is needed, but there are still a few multiplies involved.

If this is too slow, consider why you have so many comparisons to begin with. For example, it looks like you're using a grid structure: can you check for objects only in the local neighborhood by using grid coordinates (relative integers)? Can you use some other spatial data structure?

Comment
Add comment · Show 1 · 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 MountDoomTeam · Feb 08, 2013 at 05:12 AM 0
Share

O$$anonymous$$G it was my fault, I left a modulo of 10 in a grid that was 12x12 and I must have spent 7 hours trying to solve an artefact further on in the code . i am a level 2 "fast" code writer now... ahem Sorry about that guys! Thank you for $$anonymous$$ching me about Vector3 precision and efficiency!

avatar image
2

Answer by nsxdavid · Feb 16, 2014 at 10:22 PM

The Unity implementation of Vector3 == already accounts for "approximately equal". The documentaiton states:

This will also return true for vectors that are really close to being equal.

Further, there appears to be an undocumented public member:

 public const float kEpsilon = 1e-005f;

One presumes that this constant is used for the "close enough" comparison.

Vector2 also have this feature.

Comment
Add comment · Show 2 · 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 gtmacd · Sep 05, 2015 at 10:41 PM 0
Share

I'm not sure why they're so intent on implementing their own compare function. It would be cleaner to pass over all the verts that are slightly off and snap them together so the unity compare picks them up.

avatar image orionsyndrome gtmacd · Nov 12, 2018 at 12:42 PM 0
Share

@gtmacd I'm a bit late but I'm not sure I follow you. This is a problem with floating point calculation that's deeply ingrained in the way floating point works, any kind of snapping would be really bad for Unity, not to mention that a snapping algorithm can't be cheap.

Vector3 == does already account for "approximately equal" The exact implementation looks like this

 return Sqr$$anonymous$$agnitude(lhs - rhs) < kEpsilon * kEpsilon;

while Equals looks like this, so there's a difference between the two

 return x.Equals(other.x) && y.Equals(other.y) && z.Equals(other.z);

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

19 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

Related Questions

Check if Material of a gameObject == a material variable (instance)? 2 Answers

Any solution For extreamly large gameworlds [Single Precision Problem] 1 Answer

Compare Scales 1 Answer

How precise is unity with it´s transforms? 2 Answers

IntVector2 Struct useful? 1 Answer


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