Search Unity

for each object in a layer, but only one of them?

Discussion in 'Scripting' started by San_Holo, Dec 30, 2014.

  1. San_Holo

    San_Holo

    Joined:
    Sep 26, 2014
    Posts:
    152
    Hi,

    Sorry about the title I was trying to be succinct...

    I'll tell you what I'm trying to do and then why I'm a little bamboozled, basically I have a number of objects each on their assigned layer in which I hope to iterate through and then get their transform location for later use, for a kind of heat-seeking icon type thing and It works fine, but what I didn't notice was if I have multiple targets these 'icons' double up on top of one another or on the same enemy-object, not always but just some times and I wondered if my code below was some how borg'd

    Code (csharp):
    1. private GameObject nearestEnemy;
    2.  
    3.         void Start ()
    4.         {
    5.                 foreach (GameObject enemy in GameObject.FindGameObjectsWithTag("Enemies")) {
    6.                         transform.position = enemy.transform.position;
    7.                         gameObject.tag = "LockedOn";
    8.                         nearestEnemy = enemy;
    9.                 }
    10.         }
    I thought that foreach statement would iterate through that layer on the objects it found, but what I'm seeing is only one target being found, perhaps its in my update and perhaps my transform location data is that just of the one 'enemy' as used in Start() hmmm not sure... the rest of my code is below:
    Code (csharp):
    1. void LateUpdate ()
    2.         {
    3.                 if (nearestEnemy != null) {
    4.                         transform.position = nearestEnemy.transform.position;
    5.                 } else {
    6.                         Destroy (gameObject);
    7.                 }
    8.         }
    I was going to use tags and check some stuff, or perhaps dump my found objects into an array and perhaps manipulate that, but perhaps I need data from those individual transforms if multiples and update those...hmmm somthing along those lines, I'm thinking aloud, need more coffee, any advice would be a boon, thanks
     
  2. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    Whats not working?
    I'd say that it is working, after the loop is finished, the object is at the location of the last enemy in the loop
     
  3. San_Holo

    San_Holo

    Joined:
    Sep 26, 2014
    Posts:
    152
    Yes the last one in the loop, now this may be down to the timing, I have this object (lets say a missile to keep everyone smiling) and it seeks out the nearest enemy and then fires but also my seek-icon (above) also follows the enemy, but lets say I fire two missiles, it finds the last one in the loop (if I haven't shot any out of existence of course) over & over again, I thought OK just fire your missiles with a sufficient timing gap in a staggered fashion and that'll sort it, but If I haven't shot any enemies or the timing is off or somethings not right then they group up on the last enemy in the group, so I need to tell the seek-icon to skip to the next enemy if one already has an icon.... etc etc
     
  4. Dameon_

    Dameon_

    Joined:
    Apr 11, 2014
    Posts:
    542
    So you need to either globally keep track of which enemies have already been targeted, or have a component on each enemy that tells you whether it's been targeted.
     
    San_Holo likes this.
  5. San_Holo

    San_Holo

    Joined:
    Sep 26, 2014
    Posts:
    152
    My missile script needed to change my enemy tag then the code above found this tag and skipped it if found...

    Code (csharp):
    1. foreach (GameObject obj in GameObject.FindGameObjectsWithTag("Enemies")) {
    2.                         float distance = (transform.position - obj.transform.position).sqrMagnitude;
    3.                         if (distance < nearestDistance && obj.tag != "LockedOn") {
    4.                                 nearestDistance = distance;
    5.                                 nearestEnemy = obj;
    6.                                 nearestEnemy.tag = "LockedOn";
    7.                                 if (TargetIcon != null && obj.transform.position.y > player.transform.position.y) {
    8.                                         Instantiate (TargetIcon, nearestEnemy.transform.position, TargetIcon.transform.rotation);
    9.                                 }
    10.                         }
    11.                 }
     
  6. Deleted User

    Deleted User

    Guest

    One thing I noticed in your latest block is that you change the tag of the enemy from "Enemies" to "LockedOn". Unless you change it back later, it will keep the changed tag and will not be found the next time this loop runs.

    If you want to target the closest enemy, you can iterate through all desired objects and compare the distance between the current object and the transform and compare it with the smallest distance between any enemy and the transform calculated so far. For example:
    Code (CSharp):
    1. public void myFunc(){
    2. float smallestDistance = Mathf.Infinity;
    3. foreach (GameObject go in ...){
    4. float distance = Vector3.Distance(go.transform.position, transform.position);
    5. if (distance < smallestDistance){
    6. smallestDistance = distance;
    7. nearestEnemy = go;
    8. }
    9. }
    10. }
     
    San_Holo likes this.