List problem with RemoveAt();

I have a couple lists that store info about the player (skin, controller num, ready to play) and one is having an error although as far as I can tell it is the same as the others.

ready.RemoveAt(controllers.IndexOf(i));
controllers.RemoveAt(controllers.IndexOf(i));
skinsChosen.RemoveAt(controllers.IndexOf(i));
menuBoxes[0].GetComponent<Image>().sprite = aPrompt;

skinsChosen and menuBoxes both give me this error:

ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.

I initialise them here:

private List<int> controllers = new List<int>();
private List<int> skinsChosen = new List<int>();
private List<bool> ready = new List<bool>();
[SerializeField] private List<GameObject> menuBoxes = new List<GameObject>();

And this is where I add items:

controllers.Add(i);
ready.Add(false);
skinsChosen.Add(0);
menuBoxes[controllers.Count-1].GetComponent<Image>().sprite = skins[0];

Also when I put in a zero (which is what controllers.IndexOf(i) was equal to when I used debug.log) both skinsChosen and menuBoxes worked.

When they did work it gave me an error telling me that I couldn’t modify the lists as this is taking place in a loop relying on one of them:

foreach(int i in controllers){

I was wondering if there were a way to get around this error.

Shouldn’t this be

ready.RemoveAt( ready.IndexOf(i));

?

(Same goes for skinsChosen)

Besides I think you can just do ready.Remove(i); and get the same effect.

And in general, here are some notes on IndexOutOfRangeException and ArgumentOutOfRangeException:

http://plbm.com/?p=236

Steps to success:

  • find which collection it is (critical first step!)
  • find out why it has fewer items than you expect
  • fix whatever logic is making the indexing value exceed the collection
  • remember you might have more than one instance of this script in your scene/prefab
1 Like
controllers.RemoveAt(controllers.IndexOf(i));
skinsChosen.RemoveAt(controllers.IndexOf(i));

You remove the element i from the controllers and then try to find it again in the next line.
If you mean that find the index of the element i in the controllers and then remove the same index across the board, then do this:

var index = controllers.IndexOf(i);
ready.RemoveAt(index);
controllers.RemoveAt(index);
skinsChosen.RemoveAt(index);
1 Like

I think that is probably it. I can just move the controller removal to the end to do the same without a temporary variable though.

I had controllers.IndexOf(i) as i wasn’t incrementing but instead taking the value of the port the controller was plugged into and so I referenced controllers to find out which one I was disconnecting as the lists lined up.

I might be able to make another list that saves the indexes of the items to be deleted and removes them in a foreach loop after the main forloop.

IndexOf() is searching. Temporary variable is a cheap stack allocation. I wouldn’t do that.

1 Like

Are these three separate correlated arrays taht you keeping these in perfect synchrony?

If so, why not make a class to contain all three items and then have one list of instances of that class?

That would keep the skin with the controller with the ready and everything.

1 Like