A quick post regarding my findings with this, I’ve googled for clarifications but it’s not immediately obvious and the answers are scattered about. I’m also posting here in case I am doing things wrong, or others have additional tips.
As we know we destroy objects in Unity using the following:
Destroy(myobject);
However, if we have generated the objects mesh ourselves, we also need to reclaim that memory. This isn’t necessary for objects where the mesh is an asset and handled automatically by Unity. To destroy the mesh (assuming you don’t want to use it for another object, we use:
Destroy(myobject.GetComponent<MeshFilter>().mesh);
I have been doing procedurally generated code for a while now, and using the above two lines has worked out fine so far. However, one of my recent projects had objects with their own materials. The materials were not part of my projects assets, they were downloaded from the web or a local file and used once for that object, then discarded. These too need to be destroyed otherwise the memory will never be reclaimed. So:
Destroy(myobject.renderer.material.mainTexture);
Destroy(myobject.renderer.material);
I’m surprised I hadn’t came across the necessity to do this before… in a previous project I nearly did, but instead managed a collection of downloaded textures and materials in a list which was shared amongst all sorts of objects… here there was no need to destroy them with the object.
But in my new project - where each object had it’s own bespoke material - I made the mistake of assuming that Destroy would also release those materials because nothing was using them. These are not garbage collected entities - just like procedurally generated meshes.
Thankfully, these oversights can be spotted with Unity’s profiler.
Lastly, it’s fairly obvious that your calls to Destroy should be in the right order (e.g. you can’t destroy an objects material if you have already destroyed the object):
Destroy(myobject.GetComponent<MeshFilter>().mesh);
Destroy(myobject.renderer.material.mainTexture);
Destroy(myobject.renderer.material);
Destroy(myobject);
Hopefully this will provide useful for some of you and you will get a nice warm feeling knowing you won’t be leaking memory - a potentially app-crashing situation on mobile.
Feel free to post if you have any better ways of doing it, or indeed if you have came across any other “gotcha” cases where you needed to destroy more than just materials and meshes which may not be immediately obvious. Just be careful that this discussion applies only to procedurally generated objects - so don’t accidentally destroy things which are in your Resources folder or project assets - this tends not to end well!