Hi, ive been trying to solve this for a couple weeks. I have a button to change targets in my game. Say there is five enemies. if target 2 is targeted it should swap to target 3, if 3 is not targetable it should check 4,5,1, then 2, reiterating back to one if it goes over five. but i think its checking zero and getting an error, still didnt work with a zero check though
public void SwapTargetButton(){
List<GameObject> guys = GameObject.FindGameObjectsWithTag ("Enemy").ToList();
int index = guys.IndexOf (target);
Debug.Log ("target is at index: " + index + "Count: " + guys.Count);
for (int i = 1; i < guys.Count; ++i) {
if (guys [(index + i) % guys.Count] != null) {
if (guys [(index + i) % guys.Count].GetComponent<EnemyController> ().targetable) {
target = guys [(index + i) % guys.Count];
break;
}
}
}
}
Line 13 is a very hairy line of code. I recommend avoiding that style of coding, even if you see it a lot on tutorials. That style of coding will prohibit you from reasoning about issues such as the one you are facing.
First - lists and arrays in C# (and most programming languages) are zero-indexed. That means the first element is at index 0, the second is at index 1, and so on. So you should actually structure your for loop like this to look at all of them.
for (int i = 0; i < guys.Count; ++i) {
Second, FindGameObjectsWithTag is not guaranteed to return the objects in the same order every time. So you need to actually create a separate array or list that you can populate with FindGameObjectsWithTag, but don’t keep calling that function every time,
Third, I’m not sure why you actually need a for loop at all. You could just do this:
List<GameObject> guys = /* some better way of gtting a list as I mentioned */
int index = guys.IndexOf (target);
Debug.Log ("target is at index: " + index + "Count: " + guys.Count);
int newIndex = (index + 1) % guys.Length;
target = guys[newIndex];
You should give the exact error message and clearly indicate which line it occurs on.
But the only way I can think of that that could would result in an index-out-of-bounds error, specifically, would be if the list “guys” were empty (zero elements).
(If you started the loop at i = 0, then it could also give an error if “target” was not found in the list, which would cause IndexOf to return -1, which is out-of-bounds in all lists. But since you are always adding at least 1 to it, I don’t think that could result in an out-of-bounds in your particular example.)
Use a global list for your enemies and manually populate it in the Inspector, this will ensure the right order. If there’s a dynamic number of enemies, you can use the Find method, but should then sort the list (if I’m understanding what you want to do correctly). And definitely do all your counting and calculations based on a 0 index, even if it’s tempting to count from 1 for readibility. This will avoid lots of issues, especially using modulus etc. The only time you’d use the “starting at 1” labeling is for on-screen stuff for the player. At least that’s how I do it and it seems to work.