(Unity 3.2) MonoBehaviour.OnDestroy bug

I’m having some diamonds in my game to pick up. When the diamond is picked up, it is destroyed. I’m handling the OnDestroy() and instantiating the particle emitter.

The problem is, when I stop the game, the same moment emitters are created for each diamond and they remain in the editor hierarchy. I assume that’s because all game objects are destroyed when the game has been stopped.

So, I think that OnDestroy coroutine should check some things, for instance if the application is playing etc.

ps yes, I know the workarounds, I will solve my problem the other way around. :wink:

destroying the object there does only sound like a good idea if your particle emitter object you instantiate has a handler that once the effect stopped playing correctly destroys it. otherwise it will exist forever kind off

Just discovered the same problem with OnDisable. Once you stop the game Unity creates my prefab that is suppose to be created when On Disable. For every thing that has the OnDisable on it. And stays in the Editor, Start the game again and they are there, Quit again and you have the double amout.

I just ran into the same problem. My items are removed from the editor hierarchy, as is the particle emitter object which is instantiated on pickup, but once I stop the game, they magically appear in the hierarchy again.

Any suggestions on how to fix that?

Guys, this is still active bug (Unity 3.4.0f5 Indie). Are there any solutions?

My current problem is that object I’m instantiating dynamically doesn’t go away when I stop the game, it stays hanging in the editor. And all this without OnDestroy() stuff. Imagine I’m creating the bullet in the runtime and then stop the game - the bullet stays in the scene. ???

Also I get the following errors when stopping the game (in the editor of course):

!go.IsActive()
UnityEngine.GameObject:Find(String)
Some objects were not cleaned up when closing the scene
!IsPlayingOrEditMode ()

Only after those errors (sporadically) happen I get those objects stucked in the scene.

Your creating/Instantiating something in a OnDestroy or OnDisable.

Never-ever use Instantiate in a OnDestroy or OnDisable function.

If your instantiating to simulate something like blood or a explosion on the death of something, Make your own system for doing those. Like use a function like

void OnDeath(){ /* do death effects here */ }

and then whenever something kills something in game instead of using Destroy make a new function like this

static void KillAndDestroy(GameObject go) { go.BroadcastMessage(“OnDeath”, SendMessageOptions.DontRequireReceiver); Object.Destroy(go); }

then anything attached to the script with a OnDeath function will get called at that point right before being destroyed.

The reason you do not want to instantiate in a disable or destroy function is the same reason that when you change levels you wouldnt want everything to explode, but not be seen – or because it causes what your experiencing now.

BDev, thanks for a prompt response.

Yes, I know the lifecycle stuff and I don’t use OnDestroy for instantiation (not anymore :))

I’ve doublechecked my code, and the only code OnDestroy OnDisable contain is IDisposable stuff (cleanup), as well as some event listener un-registration code.

Is it possible that the cause of this problem lies in references, e.g. if I have some object referencing this object in any way, or vice versa? There is a good chance that I forgot to “plug-out” some listeners.

Also, what would be your strategy when switching scenes (or reloading levels)? What if you have some objects that contain state, and they must be in the hierarchy (e.g. cannot be free singletons)? Is it a possibility to detach/attach them and walk from scene to scene, or is it the destroy/instantiate pattern the only one that’s usable?

Thanks!

Its definitely possible. Generally though i’ve only ran into this problem with things sticking around after the scene gets stopped when theres a instantiation during shutdown. But maybe you ran into a exception while the level was shutting down it could happen as well. Make sure you check the log/console. Since you mentioned listeners i take it your talking about C# events? I havn’t really dealt with what happens when you assign a method off a instance which is later destroyed but the instance delegate is still in some event handler ( i’ve always avoided it like you mentioned do as well ) but maybe it could cause some sort of side effect like what were talking about too. I would figure anything like that would be in the console however.

Anything that inherits UnityEngine.Object is not garbage collected. So simply holding a reference to some game object during the stage shutdown is harmless because once something is destroyed it evaluates to null. This can be a problem for containers though, Like if you had a List and you run through it on OnDestroy you have to expect there to be null values inside of it because of the lack of control over the order of destruction.

To answer your question about trying to keep a object to remain in heirarchy between reloads, to detach a gameobject from heirarchy it would be something like:
transform.parent = transform.root;
DontDestroyOnLoad(gameObject);

The harder part is putting it back into hierarchy once the level has been reloaded, and then also removing the newly spawned duplicates.

Nope, I’m using my own event handling mechanism, where event dispatcher is an object containing the list of subscribed listeners (actually the list of event handlers, e.g. methods, actually Dictionary<string type, method handler> :))). So there are the listeners I’m talking about. I have completely avoided C# events stuff since I had to have a total control over the order of execution.

Cool :), Still applies what i’m talking to if the method handler is off some instance of a game object which could be destroyed. Again though you might already be doing this, but you should make sure any reference to a delegate off a instance is removed from any listener code when that component gets destroyed (if the listener was not destroyed prior). And if your listener/ dispatcher is on a UnityEngine.Object ( scriptable object or monobehaviour ) you should probably clear it out on destroy.

Again though i can’t confirm the error would exist without doing those steps, but something to look into.

Also some times its good when testing stability to try calling Resources.UnloadUnusedAssets() in the middle of the game or at the start of a level. Basically it tries to go through and actually delete things which were destroyed since theres no garbage collection. You probably shouldnt use it in your final product, but it will be called automatically for some situations. Like on iphone it gets called when theres a memory warning.

Just wanted to confirm that, indeed, behind a very complex logic of framework, I found a script which inside of:

void OnDestroy() {.....}

…called this:

GameObject.AddComponent(Type componentType);

So, that clears the case for me :slight_smile:

Thanks

It would be great if it can be called automatically, but it doesn’t. Unity don’t react on iPhone memory warnings, and application gets closed by iOs when memory consumed is over the limit.