Search Unity

How to find the nearest object

Discussion in 'Scripting' started by Corva-Nocta, Oct 13, 2015.

  1. Corva-Nocta

    Corva-Nocta

    Joined:
    Feb 7, 2013
    Posts:
    801
    I have a click to move script up and running perfectly but I will eventually want to add in things that the player will use, doors, treasure chests, monsters, etc. The game functions on a grid and when a space is clicked on the player moves to that grid space, but I will need to make it so that is a useable object is clicked the player will move to the nearest grid space then use the object. I am having trouble trying to locate the nearest grid space, how does one search for the nearest object from another object? Is there an effective way to find that object within a distance? What should I be looking for?

    C# is preffered
     
  2. vintar

    vintar

    Joined:
    Sep 18, 2014
    Posts:
    90
    Code (csharp):
    1. public GameObject GetClosestObject()
    2. {
    3.   float closest = 1000; //add your max range here
    4.   GameObject closestObject = null;
    5.   for (int i = 0; i < MyListOfObjects.Count; i++)  //list of gameObjects to search through
    6.   {
    7.     float dist = Vector3.Distance(MyListOfObjects[ i ].transform.position, player.transform.position);
    8.     if (dist < closest)
    9.     {
    10.       closest = dist;
    11.       closestObject = MyListOfObjects[ i ];
    12.     }
    13.   }
    14. return closestObject;
    15. }
     
    Eater_Games likes this.
  3. Corva-Nocta

    Corva-Nocta

    Joined:
    Feb 7, 2013
    Posts:
    801
    sweet thanks!

    actually I'm having a hard time getting this script to work :(
    Just trying to set up how to find the nearest grid space (right now just a cube object) to another object (another cube object) is there a simple way to do that? I've seen a lot of scripts that find objects with a specific tag, but I need a simple find nearest object within 1.5 with tag "walkable"
     
    Last edited: Oct 13, 2015
  4. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    if you are only looking at a small area around a specific point you could try an overlapsphere check to pick up the objects within range.

    http://docs.unity3d.com/ScriptReference/Physics.OverlapSphere.html
    (think raycast "smartbomb" :D)

    this will return a list of the colliders within the radius, you can then iterate over that list per @vintar 's code


    if you want to get "snazzy" you can sort lists using the lambda functions supported in the linq namespace... but I think it might be best to work a solution "by hand" before figuring out that (google "unity linq sort distance" should get you examples of this)
     
  5. vintar

    vintar

    Joined:
    Sep 18, 2014
    Posts:
    90
    Yes sorry, I was going to mention doing an overlap sphere if you had no list of object, and totally forgot to add it, my bad :)
     
  6. BenZed

    BenZed

    Joined:
    May 29, 2014
    Posts:
    524
    Excellent answers in here. Couple of extra thoughts:

    Code (CSharp):
    1.  
    2. //I would use a couple different methods with different overloads for different purposes.
    3. //Sometimes you'll want to do a physics cast to find the gameObjects, but sometimes they wont
    4. //have colliders. Also, you might keep a reference to a collection of them.
    5. //The first two overloads use the last.
    6.  
    7. //I made these static because they don't require a reference to 'this'. This way you could
    8. //add them to a static Utility class, or make them accessible from your Custom class.
    9.  
    10. //Quick and easy. Searches all gameObjects and returns the closest to the origin.
    11. static GameObject ClosestObject(Vector3 origin)
    12. {
    13.     var gameObjects = FindObjectsOfType<GameObject>();
    14.     return ClosestObject(origin, gameObjects);
    15. }
    16.  
    17. //Returns all gameObjects with colliders within the given range of the given origin.
    18. static GameObject ClosestObject(Vector3 origin, float range)
    19. {
    20.     var list = new List<GameObject>();
    21.     Collider[] found = Physics.OverlapSphere(origin, range);
    22.  
    23.     foreach(var collider in found)
    24.         list.Add(collider.gameObject);
    25.    
    26.     return ClosestObject(origin, list);
    27. }
    28.  
    29. //Returns the closest gameObject in a given collection of gameObjects.
    30.                        //IEnumerable so that you can pass any collection into this method. Array, List, Dictionary.Values, ect
    31. static GameObject ClosestObject(Vector3 origin, IEnumerable<GameObject> gameObjects)
    32. {
    33.     GameObject closest = null;
    34.     float closestSqrDist = 0f;
    35.  
    36.     foreach(var gameObject in gameObjects) {
    37.         float sqrDist = (gameObject.transform.position - origin).sqrMagnitude; //sqrMagnitude because it's faster to calculate than magnitude
    38.  
    39.         if (!closest || sqrDist < closestSqrDist) {
    40.             closest = gameObject;
    41.             closestSqrDist = sqrDist;
    42.         }
    43.     }
    44.  
    45.     return closest;
    46. }
     
  7. Corva-Nocta

    Corva-Nocta

    Joined:
    Feb 7, 2013
    Posts:
    801
    Thanks all! I think that overlap sphere is just what I'm looking for. I could see having a list of all the game objects working, but as the game grows in size wouldn't that eat up more processor power? I was thinking just a simple raycast from the object to find what grid spaces are closest. Guess its not as easy as I was hoping. Just need something local to find the transform of the nearest grid location so I can move the player there.
     
    Last edited: Oct 14, 2015
  8. Persona001_ID_Miijii

    Persona001_ID_Miijii

    Joined:
    Apr 16, 2019
    Posts:
    2
    I want to thank you a million!!! After some time and effort, I finally got my lock on system to work. After countless searching and tweeking! X3 I know this is an old forum post, but if you're out there, thank you!!! x3
     
    infinitegamesDS likes this.