- Home /
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:
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:
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...
In the future please include code as text and mark it as code by selecting the code block and press the "101 / 010" button. It makes it easier to quote your code or to quickly test it.
If you have trouble understanding what i just said you may want to have a look at the site navigation guide which is linked on the right side.
Answer by Bunny83 · Mar 07, 2018 at 04:20 AM
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.
I tried it with 3 transform objects and two of them were ejected, that means you got the issue. Thanks a lot!
That way it should work when I just eject the transform with index zero till no transform is over anymore. Transform[1] will becom Transform[0] after the first iteration (and the former Transform[0] is gone)...
Answer by myzzie · Mar 07, 2018 at 03:32 AM
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.
FindChild can only return a single Transform so i'm sure this is intended. I guess he wants to iterate through the childs of the "CargoSpace" object. He actually does this but as you can read in my answer because he's changing the parent of the objects he messes up the IEnumerable IEnumerator that is used by the Transform class to iterate over it's children.
Answer by Raimi · Mar 07, 2018 at 04:09 AM
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
}
Your answer
Follow this Question
Related Questions
Is having a "break" in a "foreach" loop that is itself inside a "for" loop breaking both loops? 3 Answers
Instantiate inside foreach loop 1 Answer
instantiate in foreach loop only gives last string in list 2 Answers
Having an issue with breaking out of a loop 0 Answers
How can I do a foreach loop for an array of booleans? 1 Answer