So...Why is DestroyImmediate not recommended?

I have read this page 5 times, and I still have not learned why DestroyImmediate is not recommended.

All I see is this:
You are strongly recommended to use Destroy instead.
In game code you should use Object.Destroy instead

So does anyone know WHY it is not recommended?

thanks

I read other 3rd party internet blogs and all I see is Warning: Use with extreme caution, like we are handling nuclear waste or something, LOL. http://www.unitygeek.com/difference-between-destroy-and-destroyimmediate-unity-functions/
But I can’t find out why it shouldn’t be used.

7 Likes

DestroyImmediate is not recommended for the following reasons.

  • In the editor it can remove assets, even in playmode. This means a bug in your code can remove prefabs/art/sounds/scenes ect.
  • DestroyImmediate moves the destruction out of the normal script execution order. Which means OnDestroy and OnDisable will be called at unusual times. This can lead to null reference errors, or other more subtle problems.

Generally the only reason to use DestroyImmediate is in editor code.

11 Likes

This is a bit mysterious.

Destroy(gameObject2);
if (gameObject2)
{
Debug.Log(“GameObject 2 exists”);
}

I thought Unity checks to see if the gameObject2 was set to be destroyed when implicitly converting the gameObject to a bool. So the gameObject2 would evaluate to false. Does Unity not do this?
Because the Debug.Log statement is executing and I thought it wasn’t supposed to.

Even though I shouldn’t have any issues with DestroyImmediate in my case, I’ll just stick with Destroy just to be safe.

2 Likes

Destruction happens at the end of the frame. So you can still use a destroyed GameObject as normal until the end of the frame.

4 Likes

Do these null reference errors happen in the engine code or are you referring to possible scripting mistakes?

Also, I wonder about those subtle problems because I am in a situation where I need to use DestroyImmediate and I want to know if I will regret that in the future.

1 Like

Imagine you have two objects. One of them has just started trying to modify the other and the one it’s modifying has just decided to DestroyImmediate. This is the kind of problem he’s referring to by null reference errors. With a normal destroy the one that has decided to destroy itself won’t do so until all scripts have finished executing and the problem won’t occur.

Yes, you could view this as a scripting “mistake” with the solution being to check if the object exists before you modify it but that’s additional processing time that wouldn’t have been needed if you just destroyed it normally. That said if you’re only going to very occasionally modify the object that will be destroying itself it might not matter.

What’s the situation? We might be able to come up with an alternative to destroying it immediately.

Well, I wrote myself a small ECS framework which works with components-as-monobehaviours. When I remove a component I broadcast all filter-group pairs that the entity signature is changed and each filter-group checks if the entity fits their requirements.

But since Destroy call is delayed to the end of the frame, I either need to deviate the ECS world by passing along the removed component type and pretending it is actually not there, or I need to use DestroyImmediate which keeps both worlds in sync without any effort.

I don’t want to deviate the ECS world from the actual gameobjects since, as you can imagine, there can be some nasty inconsistent behaviour if a component exists on a gameobject but ECS world has already declared it removed, for a whole frame.

1 Like

I use DestroyImmediate in combination with multi-threading. (Destroy can only be called from the “main thread”.)

The null reference errors can actually also occur in the script that you are destroying. So, this can actually be null and you’ll have to check that.

if (this == null) return;

Not a very common thing to check.

1 Like

If your system is tracking changes and preventing objects from interacting if they no longer meet the requirements of the executing code then you should be fine. At least from other objects belonging to the framework.

So the nullification of references is the only reason why DestroyImmeidate is not recommended, is that correct?

1 Like

That, and the possibility that you might end up destroying assets permanently. There might be a performance overhead too based on some of the other posts I’ve read but I haven’t dug too deeply into it.

1 Like

This would be the bigger concern with calling DestroyImmediate in game code. Accidentally call it on the wrong thing and you’ve just deleted some key asset from your project. That’s why I prefer to use DestroyImmediate in editor code.

I use Git so destroying assets wouldn’t be a problem. I will look into the performance hit. Thanks for the help.

1 Like

In my project I’ve ended up in a race condition situation: I needed the object to immediately leave hierarchy and stop any physical behavior, and I couldn’t call DestroyImmediate. After some trial and error, I’ve ended up with the following solution:

  public static void SafeDestory(GameObject obj) {
    obj.transform.parent = null;
    obj.name = "$disposed";
    UnityEngine.Object.Destroy(obj);
    obj.SetActive(false);
  }

The object, deleted like this, will stop triggering any physics immediately. And it won’t be found in the hierarchy by the methods that do such a lookup. And this method can be called from any callback, event from FixedUpdate.

3 Likes

I had another issue where Destroyimmediate caused issues. Running through a list of game objects the list changed during the processing.

            foreach (Transform object in this.transform)
            {
                if (object is anything)
                {
                    Destroyimmediate(object.gameObject);
                }
            }

Just take care, the enumeration is changed nullifying an object.

1 Like

actually I prefer DestroyImmediate over Destroy since I want to make sure that the Object gets removed from hierarchy within in the very same Frame.

However I’m scared to use it now. But actually there shouldn’t happen anything unless I’m looping through a collection containing the destroyed Object as I’m destroying it? Or am I missing something?

As long as you have a single object in the list to destroy it’s fine. But looking for multiple objects you have to take into consideration the list was altered with the first destroyed object.

To go over a collection you’re modifing just go from the end of the collection to the start ( i=collection.Length/Count ; i–).

That said, don’t use DestroyImmideate unless you’re making editor code and the compiler tells you to.

I want to destroy objects within a while loop in update, if i dont use immediate the wrong object may be destroyed, as i mark for destruction a object i iterate ots shape at loop start, but due to destroy delay, maybe destroyed after the new correct object has been created.

So i think destroy cant be used reliably in this case

5his is rather necro. Probably would be better having separate thread.

But,
You can ache your objects that need to be destroyed. For example into dictionary, array, or list.
Then work on that collection, to destroy relevant objects.

1 Like