Why does a check for null in a foreach loop make Destroying work?

For example, this code:

foreach (Transform child in transform) Object.DestroyImmediate(child.gameObject);

results in the error

The object of type 'Transform' has been destroyed but you are still trying to access it.

However, this code:

foreach (Transform child in transform) 
     if (child) Object.DestroyImmediate(child.gameObject);

seems to work perfectly. Why is that?

Was just making sure. You don't have the camera as a child, do you?

3 Answers

3

This is just hunch, but the unity docs say to use Object.Destroy instead of Object.DestroyImmediate. Its possible that you are confusing the iterator.

When writing an Editor Script, you must use DestroyImmediate. You are probably right however that using Destroy would fix this issue, since the destruction would not occur immediately and therefore would not affect the children array loop. For runtime scripts this would be the recommended approach I believe.

Is the Rigidbody kinematic? Btw, you shouldn't use Time.deltaTime when you define the speed. Time.deltaTime is the time that has passed since last frame, it's useful when you update things on a frame-to-frame basis (as in an update function), but now you just define the speed once :)

I ran into this same issue, though in my case it resulted in only partial removal of children. Here's what I originally tried doing, in JavaScript:

for (var child : Transform in obj.transform) {
    DestroyImmediate(child.gameObject);
}

This code does not delete all the children with unpredictable behavior. After reading this post, I came up with the following solution:

var children : Transform[] = new Transform[obj.transform.childCount];
var x = 0;
for (var child : Transform in obj.transform) {
    children[x] = child;
    x++;
}

if(children) {
    for (var child : Transform in children) {
        if(child) {
            DestroyImmediate(child.gameObject);
        }
    }
}

First thank you for the solution of how to simply destroy childern in a for loop. I think The reason it fails without the null check is that by destroying an object you are changing the hash value and therefore ordering of the childern in the list. So you can encounter a child again after it is destroyed. Have you checked that all childern are destroyed with null checking in place.

They have all been destroyed in my tests, but I haven't tested a lot, and I won't be confident that it will always work until I get a concrete answer.

No sir. I didn't set it as a child because it's only supposed to follow the player in the x direction, not y. I did try that though just to see if it still looked bad and it does. I'm completely baffled at this point.

No it is not kinematic. Interesting point though. What do you think that would change? And you're very right about the Time.deltaTime thing. No idea what I was thinking there!