6
\$\begingroup\$

I was wondering about the method called OnDestroy in Unity (4.5.2f1) on Windows 8.1 Update 1. I know garbage collection in C# in non-deterministic, so I was wondering if game objects had OnDestroy called the moment I called Destroy on them, or when the garbage collector was invoked?

If this is not the case, what are my alternatives? I could of course just call a method inside of the object to be destroyed just before I invoke destroy, but there may be a more elegant solution available that I don't know about.

Note: I did try checking this myself, but being non-deterministic I may not be able to rely on that behavior occurring every time.

\$\endgroup\$
9
  • \$\begingroup\$ That's probably really simple to figure out with only a few lines of code... \$\endgroup\$
    – bummzack
    Jul 28 '14 at 14:58
  • 1
    \$\begingroup\$ @bummzack as it says in the note, I tested it myself but I may well be simply getting lucky with the garbage collector. I'm looking for so e kind of specification or additional documents that define the behavior with more certainty. \$\endgroup\$
    – OMGtechy
    Jul 28 '14 at 15:00
  • \$\begingroup\$ Well, if you keep a reference to the object somewhere then it shouldn't get GCed. \$\endgroup\$
    – bummzack
    Jul 28 '14 at 15:06
  • 4
    \$\begingroup\$ The references aren't actually set to null. Unity does overload the == operator so that they appear to be null, but they're still there, which can trip up certain operations including garbage collection. \$\endgroup\$
    – rutter
    Jul 28 '14 at 15:46
  • 1
    \$\begingroup\$ @rutter that's interesting. As I understand, wrapper part(.net/Mono) of the object won't get deleted since you keep the reference, but unmanaged part is actually released from the memory. \$\endgroup\$
    – Alican
    Jul 28 '14 at 16:01
4
\$\begingroup\$

Destroy(); is an explicit command to remove the object from the game scene immediately* or after a set time increment. As soon as you call it - the item is destroyed in context of the scene.

Garbage collection will take it as soon as there are no more when it is ready assuming there are no more hard references to that item. However, this is not controllable in Unity without calling the GC system object.

Unity3D - Object.Destroy()

* clarification - immediately meaning in that frame. After the Update loop the item is destroyed, it will always be done before rendering

\$\endgroup\$
6
  • \$\begingroup\$ re: "or after a set time increment", how long can that be? Also, have you got any links to back this up at all? Thank you :) \$\endgroup\$
    – OMGtechy
    Jul 28 '14 at 15:27
  • 2
    \$\begingroup\$ Per the scripting manual, there's an optional second parameter specifying a delay in seconds. Although the destroy isn't actually called immediately; it's scheduled to be called at the end of the current Update cycle. \$\endgroup\$
    – rutter
    Jul 28 '14 at 15:49
  • \$\begingroup\$ @OMGtechy - their Reference has the answers man, just need to look. docs.unity3d.com/ScriptReference/Object.Destroy.html \$\endgroup\$ Jul 28 '14 at 15:49
  • 1
    \$\begingroup\$ @Blue: sorry for pointing out but your answer isn't completely correct. Garbage collection won't necessary happen immediately when an object has no more ref count (es.it's the garbage collector that decide based on its policy when to perform it). And garbage collection has nothing to do with other than the Mono side of the applications (scripts). Everything else is managed in a different way by the engine. \$\endgroup\$
    – Heisenbug
    Jul 28 '14 at 16:19
  • 1
    \$\begingroup\$ I would add that OnDestroy is called before rendering and after Update \$\endgroup\$ Jul 29 '14 at 19:58
2
\$\begingroup\$

Some clarifications.

Only memory allocated by scripts is managed and can be garbage collected. So if you destroy a GameObject the attached script can be eventually collected, but the life time of resources allocated from the C++ side of the engine is managed in a different way.

You can force a garbage collection explicitely call GC.Collect. If you don't force it, it's up to garbage collector decide when free the memory with zero ref count.

For what concern GameObject.DestroyImmediate I cite the doc:

This function should only be used when writing editor code since the delayed destruction will never be invoked in edit mode. In game code you should use Object.Destroy instead. Destroy is always delayed (but executed within the same frame).

I think the main reasons for that are 2:

  1. Other objects may try to access the deleted object within the same frame, so it's better to let it leave until all Update functions have been called.
  2. From a memory management point of view it could be convenient to handle allocations/deallocations in specific moment.

Despite you destroy or destroy immediate an object, the used resources aren't necessary unallocated immediately.

Just an example, suppose your destroyed GameObject has a Material referencing a Texture, even if that resource is used only by the destroyed object, it's still up to unity decides when deallocate the relative memory. If you want to force the release of unused resources you can have a look at Resources.UnloadUnusedAssets.


EDIT

As DarioOO pointed out, Unity overrides the comparison operator, in such a way that when an object has been destroyed all C# references to it are null (even if the related resources aren't still been released).

\$\endgroup\$
1
  • \$\begingroup\$ I would add that once "OnDestroy" is called, the GameObject and all connected components will no longer be available to users' code. References to those objects will return a null pointer (and the dirty stuff is that such null pointer is returned by an overloaded operator .. O_O so tecnhically those are still valid but weak references that will be collected soon or later) \$\endgroup\$ Jul 29 '14 at 19:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .