Creating a Self-Destructing Texture2D? (To prevent memory leaks)

Texture2D does not delete itself. Any new Texture2D objects you make must be processed with UnityEngine.Object.Destroy(texture2D) by the end of their lifespan or they will live in memory forever.

I thus was interested to build a class that will automatically destroy the Texture2D it contains when it goes out of scope.

ie.:

public class Texture2DManaged
{

    public Texture2D texture2D;

    public Texture2DManaged(int width, int height) {
        texture2D = new Texture2D(width, height);
    }

    ~Texture2DManaged() {
        Debug.Log("DESTRUCTOR RUN");
        UnityEngine.Object.Destroy(texture2D);
        texture2D = null;
    }
}

Then, in an Update() loop on any game object to test:

if (Input.GetMouseButtonDown(0)) {

            Texture2DManaged texture = new Texture2DManaged(5000, 5000);
            //UnityEngine.Object.Destroy(texture.texture2D);

        }

This code as is runs the DESTRUCTOR RUN debug code, but yet memory use continually rises in the Profiler when you click. By contrast, if you enable the Destroy line in the Update on click loop, this memory rise stops.

Ie. The Destroy line works correctly on mouse click but not correctly in the destructor. Any thoughts or solutions?

Sorry but this behaviour is true of ANY UnityEngine.Object.

Since anything inheriting from that class lives in both the C# and C++ sides of Unity, thus you are responsible for destroying it when no longer required.

Destructors/Finalisers do not work on UnityEngine.Objects, or at least not in the way you want them to.

1 Like

The managed Garbage Collector doesn’t call destructors as soon as an object runs out of scope but whenever garbage collection happens. Your code mostly allocates native and only a very small amount of managed memory so it might run a while and not run out of managed memory and thereby trigger the GC.

If you want to have that holder object destructed on leaving the scope, an IDisposable pattern and a using scope might work better for those purposes.

2 Likes

IDisposable is, indeed, exactly what you want. The statement form of using is very convenient:

using SomeType someName;

This will dispose of the object once it goes out of scope.

2 Likes