Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Argument is out of range. Parameter name: index (SOLVED)

Discussion in 'Scripting' started by behdadsoft, Feb 18, 2018.

  1. behdadsoft

    behdadsoft

    Joined:
    Aug 25, 2012
    Posts:
    152
    Hi.

    I wrote below code and when i remove element from box List it give me index error. so after remove element and before back to next loop and give me index error, i need update box List index.

    Code (CSharp):
    1.                
    2. for (int i = 0; i < box.Count; i++)
    3. {
    4.     for (int j = 1; j <= ChildNumber; j++)
    5.     {
    6.         if (box[i].transform.parent.name == "child" + j)
    7.         {
    8.             box.Remove(box[i]);
    9.         }
    10.     }
    11. }
    12.  
    NOTE: error occur a this line:
    Code (CSharp):
    1. if (box[i].transform.parent.name == "child" + j)
     
  2. fire7side

    fire7side

    Joined:
    Oct 15, 2012
    Posts:
    1,819
    It's not a good idea to remove an element inside a forloop using the List's count. It's better to save the index in a variable, and then remove it after finishing the loop. I'm not sure how that would work if there were multiple indexes, though, because the index would change after the removal unless you start from the largest.
    I think it's possible you are removing the same element twice, because you are cycling through j and always removing the same index of box.
     
    Last edited: Feb 18, 2018
  3. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,186
    If you need to remove from a list while looping through it, do the list in reverse. Start at the end of it and subtract and move to the first entry. This keeps you from getting the error as stuff you've already checked will shift, but the stuff you are still checking will not.
     
  4. behdadsoft

    behdadsoft

    Joined:
    Aug 25, 2012
    Posts:
    152
    i did it but it also give me error.
     
  5. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    Please post your updated code, just in case :)
     
    ucaduque likes this.
  6. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    This should work, if I understand what you're trying to do

    Code (csharp):
    1. bool shouldRemove;
    2. foreach (GameObject singleBox in box.ToArray())
    3. {
    4.     shouldRemove = false;
    5.     for (int j = 1; j <= ChildNumber; j++)
    6.     {
    7.         if (singleBox.transform.parent.name == "child" + j)
    8.         {
    9.             shouldRemove = true;
    10.         }
    11.     }
    12.     if (shouldRemove)
    13.     {
    14.         box.Remove(singleBox);
    15.     }
    16. }
    So, you don't want to remove a box in your 2nd for loop because you're still using it in the same loop. You also don't want to remove elements from a list while you are iterating through the list.

    So the way I'm doing it above is I just set shouldRemove to true if I should remove this singleBox, and then remove it when I stop using it. Instead of iterating through the list itself I convert it to an array and iterate through the array version. That makes it safe to remove items from the original list while I'm iterating through the array, since the array version actually won't change even when items are removed from the original list.
     
    Last edited: Feb 19, 2018
    behdadsoft likes this.
  7. behdadsoft

    behdadsoft

    Joined:
    Aug 25, 2012
    Posts:
    152
    Code (CSharp):
    1.  
    2. for (int i = 0; i < box.Count; i++)
    3. {
    4.     for (int j = ChildNumber; j > 0; j--)
    5.     {
    6.         if (box[i].transform.parent.name == "child" + j)
    7.         {
    8.             box.Remove(box[i]);
    9.         }
    10.     }
    11. }
     
  8. TaleOf4Gamers

    TaleOf4Gamers

    Joined:
    Nov 15, 2013
    Posts:
    825
    You are still counting up!
    Make the first for loop go in reverse too ;)
     
    behdadsoft likes this.
  9. behdadsoft

    behdadsoft

    Joined:
    Aug 25, 2012
    Posts:
    152
    Thanks Joe-Censored.
    It work very well.
    but seem without using shouldRemove variable it better work. because it make remove all index. the best option is, change for-loop to foreach-loop and then convert List to Array.

    Code (csharp):
    1.  
    2. foreach (GameObject singleBox in box.ToArray())
    3. {
    4.     for (int j = 1; j <= ChildNumber; j++)
    5.     {
    6.         if (singleBox.transform.parent.name == "child" + j)
    7.         {
    8.             box.Remove(singleBox);
    9.         }
    10.     }
    11. }
    12.  
     
    Last edited: Feb 19, 2018