-1

I have a list of this Class:

public class EachEnemy
{
    public GameObject enemy;
    public Vector3 coords;
    public float distance;

}

And they calculate the 'distance' to a Ship. As the enemies spawn and move, the distance variables changes all the time.

I need to find which is the smallest of those distances inside the List of that Class, and its index so I can target the Enemy object.

3 Answers3

1

You can use Linq OrderBy like

using System.Linq;

...

// Wherever you get this from
List<EachEnemy> allEnemies;

// Sorted by the distance to this object
var sortedEnemies = allEnemies.OrderBy(enemy => (transform.position - enemy.coords).sqrMagnitude);
// Or depending on how your class is used simply
//var sortedEnemies = allEnemies.OrderBy(enemy => enemy.distance);

// This would return null if the list was empty
// Or the first element of the sorted lost -> smallest distance  
var nearestEnemy = sortedEnemies.FirstOrDefault();

Note that using

OrderBy(enemy => (transform.position - enemy.coords).sqrMagnitude);

Would be more efficient than actual calculating the distances first since it skips using a square root on all the vector sqrMagnitudes. Since a > b also implies a² > b² and we know that a magnitude is always positive it is enough to know the sqrMagnitudes of all the delta vectors in order to sort them.

The advantage of this would be that you can also get the second and third closest enemies etc.

derHugo
  • 83,094
  • 9
  • 75
  • 115
  • 2
    Nonetheless, implementing O(n log n) when O(n) would do makes no sense. The data doesn't need to be sorted; the OP just wants the item with the smallest value, which can be found in linear time. – Peter Duniho Oct 23 '20 at 01:22
0

You can go over each item in the list and save value outside the loop, and also save the index outside the loop, e.g.

EachEnemy someFuncname(List<EachEnemy> list) 
{
    int index = 0;
    EachEnemy ea = null;
    float distance = 9999 ///
    
    foreach (var Enemy in list) {
        if (Enemy.Distance < distance) {
            ea = Enemy;
    }
    return ea;
}

You can also return the index in the same way.

Joe Mayo
  • 7,501
  • 7
  • 41
  • 60
0
float smallestDistance = eachEnemyList[0].distance;

    int index = 0;

    for(int i = 1; i < eachEnemyList.Count; i++)
    {
        if(eachEnemyList[i].distance < smallestDistance)
        {
            smallestDistance = eachEnemyList[i].distance;

            index = i;
        }
    }

This is probably not perfectly optimized but should do just fine. This gives you both the smallest distance and the index of the EachEnemy class containing the smallest distance.

Jacob M
  • 111
  • 2
  • 6