Looping through children ignores one

Hi,
I’ve been using a foreach loop to make a level generator, which basically makes tiles “spread” to fill up the available space, while making hallways. However, for each time i run the foreach loop, one tile gets left out (always the last one). Here’s a little diagram.

image

The orange squares represent the new tiles, and are supposed to go underneath each red one, but for some reason, one of them gets skipped. When looking in the Heirarchy, it’s always the last child.

This may seem like a minor problem, but eventually it happens so much the entire algorithm breaks and makes things like softlocks and weird-shaped hallways. A simplified version of the code:

foreach (Transform child in this.gameObject.transform) {
    CellScript script;
    script = child.GetComponent<CellScript>();
    //there's more code here to determine whether to go up, down, etc.
    //for example, let's make it always go down
    if (!isTileOccupied(x, y - 1) {
        createCell(x, y - 1);
    }
}

If anyone could help, that would be very much appreciated

I would start by inserting this line at the start of your foreach loop:

Debug.Log($"The foreach loop is handling {child.gameObject.name}");

If you run it again and don’t see ‘The foreach loop is handling problem child’, then you know that the loop’s not touching it. I don’t see anything wrong with the code that creates the loop, so that might suggest:

  • The problem child doesn’t exist yet when you start the loop
  • It isn’t actually a child yet when you start the loop
  • You’re doing something after the loop starts which changes the parent’s list of children, and causes weird behaviour as a result

The last one is a bad idea because it’s generally problematic to change a collection that you are currently iterating through.

On the other hand, if you run the code and do see ‘The foreach loop is handling problem child’, then you know that the loop is reaching the problem child and the problem is somewhere below that. So you add a similar Debug.Log to the next code that you would expect to run, and see if it does; and so on, until you’ve found the problem.

Hope this helps!