Sort Items Based on distance to Camera

Hi, I’ve been stuck on this problem for a week now and I can’t figure out what I’m doing wrong. Can anybody help?

The situation

The player is able to move the camera around the game field. When the player presses ‘fire’, the tower closest (or second-closest) to the camera should fire.

The towers are held in a list. When the player presses ‘fire’, the list is sorted. A delegate is used for sorting. The delegate finds the distance from one tower to the camera and compares it to the distance of another tower to the camera. This should put the list of towers in order from nearest to farthest from the camera. At this point, either index 0 or 1 is selected.

What’s happening / what I don’t understand

Regardless if the player moves the camera, the list is sorted differently every time ‘fire’ is pressed. Strangely, the sort order alternates between 2 specific orders. The tower list starts out with tower ID’s in this order: 0,1,2,3,4,5 and after firing, the order changes to 3, 4, 5, 0, 1, 2. Firing again returns to 0,1,2,3,4,5. Then back to 3,4,5,0,1,2. So it alternates between these two orders.

Following is my code. What do I have wrong, or what do I need to change, to make it do what I want it to do?

This is the sorting delegate:

public static int TowerComparison (TowerWeapon a, TowerWeapon b) {
    Vector3    camPosition = Camera.main.transform.position;
    float distA = Vector3.SqrMagnitude(a.transform.position - camPosition);
    float distB = Vector3.SqrMagnitude(a.transform.position - camPosition);

    if (distA > distB) return 1;
    if (distA < distB) return -1;
    return 0;
}

This is the ‘fire’ code:

//    listen for player input to fire
void Update () {

    //    no point in going further if the player hasn't tried to fire
    if (!Input.GetMouseButtonDown(0)) return;

    //    order the weapons from closest to furthest from the camera
    //    "weapons" type is List<TowerWeapons>
    weapons.Sort (GameUtilityMethods.TowerComparison);

    //    solution attempt #3 -- using for loop
    //    "numTowersAvailable" is a constant > 0 and < "weapons" length
    for (int i = 0 ; i < numTowersAvailable ; i++) {
        if (weapons*.IsReady()) {*

weapons*.Fire (target);*
break;
}
}
}
Thanks for any insight you can offer!

float distA = Vector3.SqrMagnitude(a.transform.position - camPosition);
float distB = Vector3.SqrMagnitude(a.transform.position - camPosition);

Did you really mean to use “a” twice? distA and distB will always be the same, and as such your function always returns 0.

Correct code would be:

float distA = Vector3.SqrMagnitude(a.transform.position - camPosition);
float distB = Vector3.SqrMagnitude(b.transform.position - camPosition);