I was trying to loop through all the children of a gameobject changing its parent (using c#). I was using the following code:
foreach (Transform tempTransform in transform){
tempTransform.parent = null;
}
The code is pretty clean, but the problem is that it only changes some of the children (only the odd ones). I can do this in many other ways but this is by far the best. If I make any other action on it, for example rename them it works, the problem comes only when parenting
The child list is being updated when you re-parent inside that loop so the internal incrementation is skipping every 2nd one. Think of it as iterating over an array, but each time through the loop you change the size of the array youâre currently looping though - naturally things are going to go a bit wrong.
Building a copy of the list first should fix this problem.
Transform[] children = new Transform[](transform.childCount);
int i = 0;
foreach (Transform tempTransform in transform){
children[i] = tempTransform;
i++;
}
i = 0;
while(i < children.Length) {
children[i].parent = null;
i++
}
Thank you all. Now I know why that happens. The âworkaroundâ I was using was the one proposed by Cameron, but the other ones are also great for other situations.
Before you start the loop, your structure looks like this:
root
|-child1 â This is the first element which gets called when you enter your loop
|-child2
|-child3
|-child4
|-child5
|-child6
So for each returns a reference to the first child, child1. When you do child1.parent = null; it will be removed from the structure.
root
|-child2 // Youâre still in your FIRST iteration!!!
|-child3
|-child4
|-child5
|-child6
after that, the next element will be called, so the next iteration.
root
|-child2
|-child3 <â This is where your code points after the second iteration!
|-child4
|-child5
|-child6
What happend? Because you removed the first element, everything moved up. The child2 became 1st child, the child3 became 2nd child etc. On the next iteration it selected the next child, child3.
If transform changes while youâre inside the loop such effects can happen. With the examples from above, you first read all childs into a separate array, so no matter if âtransformâ changes, you already have all references to the childs you needed and this effects donât happen
One of the way you could have done it with one for loop could have been:
This will always remove the top-most (aka first) transform, until âtransform.childCountâ is zero. However, this is not really recommended to do in general. Itâs not very clean or readable. The code examples from above all make a better readable code. Itâs just âfor recordâ.
Sorry for responding to such an old thread but I stumbled upon this through google searches and figured others would to. I solved this by using a generic list . . .
//Dont forget to add: using System.Collections.Generic; to the top of the script...
//create a new list
List<Transform> childrenList = new List<Transform>();
//add all children of the transform to the new list
foreach(Transform childTrans in transform)
childTrans.Add(childTrans);
foreach(Transform childTrans in childrenList)
//do stuff