Search Unity

[Solved]Use array to count first objects nearest me ?

Discussion in 'Scripting' started by Quast, Jan 4, 2019.

  1. Quast

    Quast

    Joined:
    Jul 5, 2015
    Posts:
    560
    I'm trying to put first 3 objects"enemy" that close to me in a array. My script is working but I don't know how to program the distance correctly To put the first object that close to me number one in my array, and so on.

    Code (CSharp):
    1.     public GameObject[] Enemy;
    2.     public float distance;
    3.     public int Num_Objects;
    4.  
    5.  
    6.     void Start()
    7.     {
    8.         Enemy = GameObject.FindGameObjectsWithTag("enemy");
    9.     }
    10.  
    11.     void Update()
    12.     {
    13.         for (int i = 0; i < Enemy.Length; i++)
    14.         {
    15.             distance = Vector3.Distance(gameObject.transform.position, Enemy[i].transform.position);
    16.           // here should count the first three objects
    17.  
    18.             if (distance < 5)
    19.             {
    20.  
    21.                 Enemy[i].GetComponent<enemypath>().enemy_checker = true;
    22.             }
    23.         }
    24.  
    25.     }
     
  2. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Why not just use a list, sort the list by distance, and then assign the first 3 to your array? (or just not use an array at all)
     
    Peter77 likes this.
  3. Quast

    Quast

    Joined:
    Jul 5, 2015
    Posts:
    560
    List or Array, both good if will get me what i need. The question is how ?
     
  4. Sharlatan

    Sharlatan

    Joined:
    Jul 23, 2013
    Posts:
    111
    Just to be sure: You want the 3 enemies that are closest to you, not just any 3 that are close (whatever "close" means in that case)?
     
  5. Quast

    Quast

    Joined:
    Jul 5, 2015
    Posts:
    560
    Yes, close = closest. Sorry.
    Like any zombie game. Group of enemies attacking player.
    I want from this script to list first three of them that closest to player.
    of one die. Script will search for the third enemy that closest to player and add to list.
    That is all.
    I hope now that I cleared the function of this script. Could anyone help me with this ?
     
  6. Sharlatan

    Sharlatan

    Joined:
    Jul 23, 2013
    Posts:
    111
    Your biggest problem, preventing you from easily sorting the enemies by distance to the player, are your data structures. I can't really fix this, for that, one would have to have access to the whole project.
    The only thing I can give you is kind of a workaround that's just.. well, not super ugly but also not how you would tackle this problem in a really clean way (but to help with that, we would have to change things in a few places in the project).

    First, at the top of your file (where the other using statements are), you have to add this:
    Code (CSharp):
    1. using System.Collections.Generic;
    Then you can add/replace the following things insider your class:

    Code (CSharp):
    1.     private GameObject[] _enemies;
    2.     public int Num_Objects;
    3.  
    4.     void Start()
    5.     {
    6.         _enemies = GameObject.FindGameObjectsWithTag("enemy");
    7.     }
    8.  
    9.     void Update()
    10.     {
    11.         //putting all enemies into a wrapper that helps us sorting and adding them to a list. could also do this with linq but I assume it will be easier to understand with a foreach loop
    12.         var sortingWrapperList = new List<EnemySortingWrapper>();
    13.         foreach (var enemy in _enemies)
    14.         {
    15.             var distanceToPlayer = Vector3.Distance(gameObject.transform.position, enemy.transform.position);
    16.             sortingWrapperList.Add(new EnemySortingWrapper(distanceToPlayer, enemy));
    17.         }
    18.  
    19.         //now that the enemies are all in a list, let's sort them...
    20.         sortingWrapperList.Sort((x, y) => x.DistanceToPlayer.CompareTo(y.DistanceToPlayer));
    21.         //instead of the line above, you could also use the following line, in case that's clearer to you but you would have to add "using System.Linq;" to the top of your file!:
    22.         //sortingWrapperList = sortingWrapperList.OrderBy(w => w.DistanceToPlayer).ToList();
    23.  
    24.         //now that we have everything sorted, we can access the enemy game objects as follows:
    25.         sortingWrapperList[0].Enemy.GetComponent<enemypath>().enemy_checker = true; //sets enemy_checker for closest enemy
    26.         sortingWrapperList[1].Enemy.GetComponent<enemypath>().enemy_checker = true; //sets enemy_checker for second closest enemy
    27.         sortingWrapperList[2].Enemy.GetComponent<enemypath>().enemy_checker = true; //sets enemy_checker for third closest enemy
    28.     }
    29.  
    30.     private class EnemySortingWrapper
    31.     {
    32.         public float DistanceToPlayer { get; private set; }
    33.         public GameObject Enemy { get; private set; }
    34.  
    35.         public EnemySortingWrapper(float distanceToPlayer, GameObject enemy)
    36.         {
    37.             DistanceToPlayer = distanceToPlayer;
    38.             Enemy = enemy;
    39.         }
    40.     }
    Hope that helps
     
    Quast likes this.
  7. Sharlatan

    Sharlatan

    Joined:
    Jul 23, 2013
    Posts:
    111
    Sorry for the double post. But saw, that you already liked my comment. A minute or two after posting, I noticed a super small error and corrected it (always used "0" for the list element access at the end and not 0, 1 and 2). Already fixed it; but just so you're aware!
     
    Quast likes this.
  8. Quast

    Quast

    Joined:
    Jul 5, 2015
    Posts:
    560
    Thank you so much Sharlatan. I found that will be easy for me to use List instead of Array.
    Here is how "some one solved for me".
    Code (CSharp):
    1.     public List<GameObject> enemiesInRange = new List<GameObject>();
    2.     public int hox;
    3.     int SortByDistanceToMe(GameObject a, GameObject b)
    4.     {
    5.         float squaredRangeA = (a.transform.position - transform.position).sqrMagnitude;
    6.         float squaredRangeB = (b.transform.position - transform.position).sqrMagnitude;
    7.         return squaredRangeA.CompareTo(squaredRangeB);
    8.     }
    9.  
    10.     // Update is called once per frame
    11.     void Update()
    12.     {
    13.  
    14.         enemiesInRange.Sort(SortByDistanceToMe);
    15.        
    16.         hox = enemiesInRange.Count;
    17.         if (hox == 3)
    18.             print("Frist enemy near you is " + enemiesInRange[0] + ", " + enemiesInRange[1] + ", " + enemiesInRange[2]);
    19.  
    20.         //   enemiesInRange[0].GetComponent<enemypath>().enemey_checker = true;
    21.         //   enemiesInRange[1].GetComponent<enemypath>().enemey_checker = true;
    22.         //   enemiesInRange[2].GetComponent<enemypath>().enemey_checker = true;
    23.  
    24.     }
    25.  
    26.  
    27.     void OnTriggerEnter(Collider other)
    28.     {
    29.         if (other.CompareTag("enemy") && hox < 3) // list have three enemies
    30.             enemiesInRange.Add(other.attachedRigidbody.gameObject);
    31.     }
    32.  
    33.     void OnTriggerExit(Collider other)
    34.     {
    35.         if (other.CompareTag("enemy"))
    36.             enemiesInRange.Remove(other.attachedRigidbody.gameObject);
    37.     }
     
  9. Sharlatan

    Sharlatan

    Joined:
    Jul 23, 2013
    Posts:
    111
    No problem, happy to hear you've got something that works.
    But maybe next time let us know in your thread when you've got a working solution, so other people don't spend time on solving it as well and can instead help someone else :)
     
    Last edited: Jan 5, 2019
    Quast likes this.
  10. Quast

    Quast

    Joined:
    Jul 5, 2015
    Posts:
    560
    Just before one hour from you reply, this guy respond to my issue and solved. Keep in mind that of course your script will help other people not just me. I really appreciate what you did for me. Thank you again
     
  11. Sharlatan

    Sharlatan

    Joined:
    Jul 23, 2013
    Posts:
    111
    No problem at all! Hope it didn't across annoyed, that certainly wasn't the intention!
    And nice of you to post the other solution as well; it might people give some more inspiration how to solve such problems :)
     
    Quast likes this.