Search Unity

[SOLVED] Find nearest object in array, destroy it, move to next nearest...

Discussion in 'Scripting' started by krougeau, May 25, 2015.

  1. krougeau

    krougeau

    Joined:
    Jul 1, 2012
    Posts:
    456
    I was attempting to assist another user with an issue here on the forums, got them to a certain point, and then they stumped me... Here's the gist: He wants to locate the nearest all items in the scene tagged as "object", locate the nearest one, move to it, destroy it OnTriggerEnter, then continue on with the next nearest object, ad infinitum, until all of them have been destroyed. I was able to get them so far as moving to and destroying the first object tagged as "object", but I'm at a loss as to how to proceed. I've spent nearly two hours now combing through example code snippets and documentation, but can't for the life of me find something that will work for these particular circumstances. Any assistance would be greatly appreciated, not to mention highly educational. I'm at my wits end... Here's the "working" script as it sits, minus the many, many changes I've made trying to get it to work in my test scene:

    Code (CSharp):
    1.     using UnityEngine;
    2.     using System.Collections;
    3.  
    4.     public class enemys : MonoBehaviour {
    5.        
    6.         private float speed = 1.5f;
    7.         public GameObject object1;
    8.         private GameObject[] objects1;
    9.         private GameObject nearestTarget;
    10.         private float distance;
    11.         private float curDistance;
    12.         private Vector3 pos;
    13.         private Vector3 diff;
    14.  
    15.         void Start()
    16.         {
    17.             nearestTarget = null;
    18.             distance = Mathf.Infinity;
    19.             pos = transform.position;
    20.             objects1 = GameObject.FindGameObjectsWithTag("object");
    21.             FindTarget();
    22.         }
    23.  
    24.         void Update ()
    25.         {
    26.             if (object1 != null)
    27.             {
    28.                 transform.position = Vector3.MoveTowards (transform.position, object1.transform.position, speed);
    29.             }
    30.         }
    31.  
    32.         void OnTriggerEnter(Collider other)
    33.         {
    34.             if (other.gameObject.CompareTag ("object"))
    35.             {
    36.                 Destroy(other.gameObject);
    37.                 FindTarget();
    38.             }
    39.         }
    40.  
    41.         void FindTarget()
    42.         {
    43.             foreach (GameObject obj in objects1)
    44.             {
    45.                 diff = obj.transform.position - pos;
    46.                 curDistance = diff.sqrMagnitude;
    47.                 if(curDistance < distance)
    48.                 {
    49.                     nearestTarget = obj;
    50.                     object1 = nearestTarget;
    51.                     distance = curDistance;
    52.                 }
    53.             }
    54.         }
    55.     }
    And here's a link to their original thread:
    http://forum.unity3d.com/threads/er...oes-not-denote-a-valid-type-not-found.327951/
     
  2. Nitugard

    Nitugard

    Joined:
    May 10, 2015
    Posts:
    343
    Working code:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using System.Linq;
    5.  
    6. public class PlayerController : MonoBehaviour
    7. {
    8.  
    9.     private float speed = 1.5f;
    10.     public GameObject object1;
    11.     public List<GameObject> objects1 = new List<GameObject>();
    12.  
    13.     void Start()
    14.     {
    15.         pos = transform.position;
    16.         objects1 = GameObject.FindGameObjectsWithTag("object").ToList();
    17.         FindTarget();
    18.     }
    19.  
    20.     void Update()
    21.     {
    22.         if (object1 != null)
    23.         {
    24.             transform.position = Vector3.MoveTowards(transform.position, object1.transform.position, speed);
    25.         }
    26.     }
    27.  
    28.     void OnTriggerEnter(Collider other)
    29.     {
    30.         if (other.gameObject.CompareTag("object"))
    31.         {
    32.             objects1.Remove(other.gameObject);
    33.             Destroy(other.gameObject);
    34.             FindTarget();
    35.         }
    36.     }
    37.  
    38.     void FindTarget()
    39.     {
    40.  
    41.         float lowestDist = Mathf.Infinity;
    42.  
    43.  
    44.         for(int i=0; i<objects1.Count; i++)
    45.         {
    46.  
    47.             float dist = Vector3.Distance(objects1[i].transform.position, transform.position);
    48.  
    49.             if (dist<lowestDist)
    50.             {
    51.                 lowestDist = dist;
    52.                 object1 = objects1[i];
    53.             }
    54.          
    55.         }
    56.     }
    57. }
    Hope this helps :)
     
    Last edited: May 25, 2015
    krougeau likes this.
  3. Epic-Username

    Epic-Username

    Joined:
    May 24, 2015
    Posts:
    339
    2 issues with this it doesn't find closest one it destroyed them in order from creation and i have a spawner going so the list has to be updated repeatedly and i don't know how to add newly created objects to a list.
     
  4. Nitugard

    Nitugard

    Joined:
    May 10, 2015
    Posts:
    343
    I tried this and its working perfectly fine! When you spawn new object just updated the list like this:
    Code (CSharp):
    1. objects1.Add(object);
     
    krougeau likes this.
  5. Kragh

    Kragh

    Joined:
    Jan 22, 2008
    Posts:
    657
    I see a problem. When you find a target, you set distance equal to curDistance. It may very well be that after moving to that object, the next nearest object is further away from your object, than last search. But you will never accept that distance in your code, because it has to be less than "distance".

    So... here's the deal. You have to treat each search of the nearest object without looking a last search. Clear your distance variable.
    After the "for each" loop:

    Code (csharp):
    1. distance = Mathf.Infinity;
    And also, what happens if by chance your object hits another "object" while moving towards the goal object? Why not test against the object you are moving towards?:

    Code (csharp):
    1. if(other.gameObject  == object1)
    Hope it helps :)
     
    Last edited: May 25, 2015
    krougeau likes this.
  6. krougeau

    krougeau

    Joined:
    Jul 1, 2012
    Posts:
    456
    Thanks guys. I've been going round and round with this and another seemingly simple issue tonight and I was starting to lose confidence in myself haha.
     
    taylorjames9 and Nitugard like this.