Foreach loop wont run completely

Hi there

I’ve a foreach loop for all transforms of a gameobject; something I used many times already. But this time the loop wont run completely, stopping after one cycle.

Here’s the script:

112516-foreachloop-script.jpg

Explained: foreach transform in the gameobject “CargoSpace” should following things be made: Add the (transform)object to a list (that works). Remove it from another list (that works too). Change parent (guess what: it works). But the foreach wont work:

112518-foreachloop-console.jpg

Correctly (as I know) should happen:
A: 1 times (pressing the button once)
B: 2 times (once for each of the two objects in transform)
C: 2 times (once for each of the two objects in transform)

And yeah, there are two objects in transform.
How can I make it work for all of the objects? I’ll try it with a for loop, but thats a detour…

You change the parent of the elements you iterate over. That means you mess up the enumerator since the “collection” of objects is changed from within the loop. You effectively will skip every second element.

Have a look at this. The pipe | should represent the internally used index:

//     0    1    2    3    4    5    6    7    8
//     |
//
//     1    2    3    4    5    6    7    8
//          |
//
//     1    3    4    5    6    7    8
//               |
//
//     1    3    5    6    7    8
//                    |
//
//     1    3    5    7    8
//                         |
//
//     1    3    5    7    <--- remaining elements

So since you change the parent of the object it is no longer a child of the object you iterate over. One solution is to iterate backwards:

Transform parent = BaseItem.transform.FindChild("CargoSpace");
for(int i = parent.childCount-1; i >= 0; i--)
{
    Transform Item = parent.GetChild(i);
    // [ ... ]

Another solution is to first pull all objects into an actual array or list before you work on them. With using System.Linq; you can simply do:

var childs = BaseItem.transform.FindChild("CargoSpace").Cast<Transform>().ToArray();

This array can be safely iterated over with a foreach loop as the array is persistant and isn’t changed during iteration.

Only explanation would be that it can only find 1 transform with the name CargoSpace on the baseItem. Why don’t you iterate the list you’re removing the item from and compare it.

Not to sure. But, FindChild() returns one child called “CargoSpace”.

maybe you need a list of transforms…

List<Transform> items;

foreach(Transform t in items)
{
     //Do your thang
}