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 /
avatar image
1
Question by Smireles · Oct 16, 2015 at 12:36 AM · c#vector3transform.positiondistance check

Get closest Vector3 position from a GameObject and two Transforms (and the line inbetween them)

Hi,

I need to get a Vector3 inside the range between two Transforms, having both Transform as the limit position regarding a third GameObject floating aroung the scene.

I drew an example hoping it would help.

alt text

All those Cubes would be the same GameObject and it's possible positions, I mean, it could be anywhere... but the closest V3 would be constrained inside the line between Transform 1 and Transform 2.

I'm working in C#, but if you have the answer in JS I don't care, just need the logic or initial direction in how to solve this problem.

Thanks in advanced!

example.png (223.2 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

2 Replies

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

Answer by dkjunior · Oct 16, 2015 at 01:11 AM

Basically what you need is to draw a perpendicular from a given point to a line. Here's a function to do that (first solution that came to my head, this can probably be done more elegantly).

 private Vector3 ClosestPoint(Vector3 limit1, Vector3 limit2, Vector3 point)
     {
         Vector3 lineVector = limit2 - limit1;
 
         float lineVectorSqrMag = lineVector.sqrMagnitude;
 
         // Trivial case where limit1 == limit2
         if(lineVectorSqrMag < 1e-3f)
             return limit1;
 
         float dotProduct = Vector3.Dot(lineVector, limit1 - point);
 
         float t = - dotProduct / lineVectorSqrMag;
 
         return limit1 + Mathf.Clamp01(t) * lineVector;
     }

The function takes two limiting points (as in your example), and the location of the floating object. It returns a point on the line between two limits that is closest to the floating object.

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 Smireles · Oct 16, 2015 at 02:45 AM 1
Share

Thank you very much. This function is returning exactly what I was looking for. Good thing my drawing didn't confused you!

I need to study your answer to understand what are you doing; but it does exactly what I was asking for. Again, thank you!

PS: What's up with that 1e-3f ?? I understand that is to check if there is no distance between limit1 and limit2, but is weird to see that. Is it the same to check for something like this:

if (Vector3.Distance(limit1, limit2) == 0.0F)

avatar image dkjunior Smireles · Oct 16, 2015 at 09:50 AM 0
Share

Glad it worked for you!

The 1e-3f trick is the practical approach for perfor$$anonymous$$g floating point comparison operations. The thing with floating-point operations is that they will lose precision as you work with them. For example, if you take a (0, 0, 0) point and perform a bunch of transforms on it (move/rotate a few times) so that it eventually returns to its original location, it's very unlikely you will get exactly (0, 0, 0). What you will likely get is something like (0.000001, -0.00000012, 0.0000005). For all practical reasons it's still zeroes, but if you perform a vanilla comparison with 0.0, it won't match and give you many headaches. So whenever you need to compare floating point values for equality it is recommended that you test not for an exact match but for them being within very small distance from each other.

Regarding the algorithm itself, it's basically using line equation in a parameterized form:

p = limit1 + (limit2 - limit1) * t

where each point p belonging to this line is represented by certain value of parameter t. It then tries to find such a value t so that the distance between the point on the line p (corresponding to that t) and your floating point is $$anonymous$$imal. Once found it puts t into line equation to get the point on the line you are looking for. Clamping of t is done so that the resulting point always stays between the limits.

avatar image Dave-Carlile dkjunior · Oct 16, 2015 at 12:19 PM 0
Share

Unity also has the $$anonymous$$athf.Approximately function that does this same thing in a slightly more readable way.

Show more comments
avatar image
0

Answer by Bunny83 · Oct 16, 2015 at 01:19 AM

 // input values
 Transfrom a;
 Transform b;
 Transform[] gameobjects;
 
 // output values
 Transform closest = null;
 Vector3 pos;
 
 float minDist = float.PositiveInfinity;
 Vector3 posA = a.position;
 Vector3 posB = b.position;
 Vector3 d = (posB - posA).normalized;
 for(int i = 0; i < gameobjects.Length; i++)
 {
     Vector3 p = gameobjects[i].position;
     Vector3 v = p - posA;
     Vector3 point = posA + Vector.Project(v, d);
     float dist = (point - p).sqrMagnitude;
     if (dist < minDist)
     {
         minDist = dist;
         closest = gameobjects[i];
         pos = point;
     }
 }

Untested but should work.

edit
It's hard to tell from your drawing if an object that actually is close to the "ray" that your two transforms defines but it's projected point is outside the line segment what distance you want to calculate.

One way would be to define two Planes which specifiy the ends of the line:

 Plane p1 = new Plane(d,posA);
 Plane p2 = new Plane(-d,posB);

Inside the for loop you would do:

     Vector3 v = p - posA;
     Vector3 point = posA + Vector.Project(v, d);
     if (!p1.GetSide(p))
         point = posA;
     if (!p2.GetSide(p))
         point = posB;
     float dist = (point - p).sqrMagnitude;
     // ....

That way you get a capsule shape around your line.

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 Smireles · Oct 16, 2015 at 02:49 AM 0
Share

Hello Bunny83! Thanks for answering my question. I will try you code in my testing environment to see how it works.

The answer above worked perfectly when implemented in my project. But I will try and learn from your solution as well. $$anonymous$$orrow when I get back to work I will jump into it.

Thanks again for your time man, have a great day.

PS: Sorry for my drawing, I bet is kinda confusing without the proper description. :p

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

32 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

Related Questions

How do I make and object's position and rotation independent again? 1 Answer

Calculate the distance between an object and my player 1 Answer

Adding rotation to Physics.AddForce(); ... Getting weird error? 0 Answers

Multiple Cars not working 1 Answer

Nav Mesh and transform.position failure! 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