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
1
Question by basil4j · Sep 14, 2013 at 04:21 AM · c#distance

Most efficient way to check distance between player and scene objects

Hi. I need various objects in each of my scenes to do something when the player is within a certain distance. Is it better to attach the distance checking script to each object or to attach it to the player and loop through each object?

Im using c#

Thanks!

Comment
Add comment · Show 1
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 Juanm45 · Oct 25, 2021 at 06:30 PM 0
Share

Thanks for the information, I will try to figure it out for more. Keep sharing such informative post.

4 Replies

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

Answer by vexe · Sep 14, 2013 at 05:43 AM

Interesting question. In my opinion do what @iwaldrop told you, logic-wise. Really nice logic he made there (+1) it depends on who's doing what.

However performance-wise, It's not like you're gonna get a boost if you're gonna calculate the distance from your objects (or vise versa), simply because for example if you have 100 objects, the distance instruction will get executed 100 times no matter what (let it be Vector3.Distance)

To prove it, I went in for some benchmarking. Here's my test environment:

I have a CubeSpawner.cs script attached to my main camera, that spawns a number of cubes:

 public class CubeSpawner : MonoBehaviour
 {
    public int nCubes;
    public GameObject cube;
    public List<GameObject> allCubes = new List<GameObject>();
    private Transform _transform;

    void Awake()
    {
       _transform = transform;
    }
 
    IEnumerator Start()
    {
       for (int i = 0; i < nCubes; i++)
       {
         var randVect = new Vector3(Random.Range(-50, 50),
                                    Random.Range(-50, 50),
                                    Random.Range(-50, 50));
         allCubes.Add((GameObject)Instantiate(cube, _transform.position + randVect, Quaternion.identity));
         yield return null;
       }

       var watch = new Stopwatch();
       watch.Start();
       for (int i = 0, len = allCubes.Count; i < len; i++)
       {
           var dist = Vector3.Distance(_transform.position, allCubes[i].transform.position);
           yield return null;
       }
       watch.Stop();

       Debug.Log("SPAWNER to CUBE: " + watch.ElapsedMilliseconds);
       Debug.Log("CUBES to SPAWNER: " + CubeScript.totalTime);
    }
 }

Here's my CubeScript.cs:

 public class CubeScript : MonoBehaviour
 {
     public Transform target;
     public static double totalTime = 0;
     private Transform _transform;
 
     void Awake()
     {
         _transform = transform;
         target = Camera.mainCamera.transform;
     }
 
     IEnumerator Start()
     {
         var watch = new Stopwatch();
         watch.Start();
 //        var init = Time.realtimeSinceStartup;
         var dist = Vector3.Distance(_transform.position, target.position);
         yield return null;
 //        totalTime += (Time.realtimeSinceStartup - init);
         watch.Stop();
         totalTime += watch.ElapsedMilliseconds;
     }
 }

(The comments shows another way to get the time took to get the dist) totalTime is static so its shared between all cubes.

Now, you might notice a strange thing, why am I doing a yield return null? Because no matter how I tried getting the total time without it, I just kept getting a zero, because it takes very little time to do a single Vector3.Distance - You can try it out for yourself.

Now that there's a yield return null after each distance calc in both the spawner and the cube scripts, we should reach balance now.

I ran a few tests, here are the results of instantiating 1000 cubes (you can think of the spawner as your player, and the cubes as the objects):

            Test#: 1     2     3     4
 SPAWNER to CUBES: 3683, 3208, 3108, 3514 (ms)
 CUBES to SPAWNER: 3776, 3240, 3461, 3453 (ms)

So, as you can see they're very close, with more wins to SPAWNER to CUBES over CUBES to SPAWNER

So performance-wise, it doesn't make that much of a difference.

And if there was a very huge number of objects that you must calculate the dist to (like 100000), I would use a yield return null to divide the pressure over separate frames every 1000 call or so.

Note that I used Vector3.Distance just to illustrate, it's more efficient to use (pos1 - pos2).sqrMagnitude if you just wanna compare between two distances like:

 (pos1 - pos2).sqrMagnitude < dist * dist
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
8

Answer by iwaldrop · Sep 14, 2013 at 05:03 AM

You can do it either way, but I'd reccomend thinking about what you want to do. If the player is going to do something when these object get in range, have the player do it.

 foreach (Transform t in otherTransforms)
     if ((transform.position - t.position).sqrMagnitude < distance * distance)
         // do something

If the objects are going to do something, have them check.

 if ((StaticPlayerPositionPropery - transform.position).sqrMagnitude < distance * distance)
     // do something


Otherwise, if both things are going to do something, it's better to have an observer do it.

 foreach (Transform t in objectTransforms)
     if ((OnObjectInRange != null &&  StaticPlayerPositionProperty - t.position).sqrMagnitude < distance * distance)
         OnObjectInRange(t);
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 whydoidoit · Sep 14, 2013 at 05:35 AM 1
Share

In your for next loop (the first one) you meant t.transform.position right?

It would also be better to cache transform.position for that loop for two reasons - doing transform takes some time, and calculating a position can be expensive especially if items have parents.

avatar image iwaldrop · Sep 14, 2013 at 05:57 AM 1
Share

Yes whydididoit, thanks for the catch; fixed. And I totally agree with the position caching, just wanted to provide a concise example.

avatar image basil4j · Sep 14, 2013 at 06:21 AM 0
Share

Wow thanks all!

That answers my question :) and I think the logic fits more in line with my game play. I will put the script on the player.

avatar image MFen · Oct 28, 2014 at 05:32 PM 0
Share

t.position (t is already a transform)

avatar image
1

Answer by Ashutosh8126 · Sep 14, 2013 at 06:46 AM

I won't recommend checking distance.. I prefer saving calculations.. I would prefer using a trigger maintains its size at the necessary distance you want.. and as any scene object collides it, then you can do anything..

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 basil4j · Sep 14, 2013 at 06:56 AM 0
Share

Thats also an interesting idea. Behind the scenes wouldnt this mean alot of math checking of the player is within the bounds of each and every trigger object?

avatar image Ashutosh8126 · Sep 15, 2013 at 09:06 AM 1
Share

No.. I believe this is the most optimized way.. ins$$anonymous$$d of checking the distance between the player and the objects in Update :)

avatar image
0

Answer by ginryu · Oct 24, 2021 at 10:58 PM

if you want to just check to see if an if an object is within the bounds of an object, instead of using distance, just take the height,width, length of an object and check to see if the players position falls within those coordinates

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

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

21 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

Related Questions

Distribute terrain in zones 3 Answers

Multiple Cars not working 1 Answer

The name 'Joystick' does not denote a valid type ('not found') 2 Answers

How can I play audio while a non player controlled object is moving and stops playing when object stands still? 1 Answer

Player lives script help 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