How to clear temporary variables from memory? Memory currently being obliterated ...

I am writing code for Unity in C#. I found a major error in the way I am writing my scripts, but I am not sure of the correct method I should be using instead. I will often create temporary lists, floats, textures, etc. in my scripts. I also often initialize my variables with new. I thought this unneeded data would just “disappear” when it was not being used. However, this is not happening as I expected.

I found this while experimenting with some code which can be simplified as:

public class PhotoTestClass {

    //public Texture2D photoTexture = new Texture2D(500,500); // USING THIS LINE CAUSES INSANE PROGRESSIVE MEMORY USE IN THE LOOP BELOW
    public Texture2D photoTexture = null; //USING THIS LINE CAUSES MILDER PROGRESSIVE MEMORY USE IN THE LOOP BELOW

    public PhotoTestClass(Texture2D setPhotoTexture = null) {
        if (setPhotoTexture == null) {
            setPhotoTexture = new Texture2D(500, 500);
        }
        photoTexture = setPhotoTexture;
    }
}

public class TestClass {

    public void TestTextureWork() {

            List<PhotoTestClass> photoClassList = new List<PhotoTestClass>();
            photoClassList.Add(new PhotoTestClass(Resources.Load<Texture2D>("photo1")));
            photoClassList.Add(new PhotoTestClass(Resources.Load<Texture2D>("photo2")));
            photoClassList.Add(new PhotoTestClass(Resources.Load<Texture2D>("photo3")));
            photoClassList.Add(new PhotoTestClass(Resources.Load<Texture2D>("photo4")));
            photoClassList.Add(new PhotoTestClass(Resources.Load<Texture2D>("photo5")));

            //would then run some operations on this temporary list and store results to persistent public/private variables
            //would like all above data created cleared from memory at end of function
    }
}

If I then inside my app run this as a function in my app on demand (eg. triggered by a button):

private void runFunction(){
       TestClass tempTestClass = new TestClass();
        for (int i = 0; i < 100; i++) {
            tempTestClass.TestTextureWork();
        }
}

In all circumstances, texture memory incrementally increases after time I run the function and does not come down. However, if I used the line public Texture2D photoTexture = new Texture2D(500,500); in PhotoTestClass, memory usage SKYROCKETS after each run by another several gigabytes each time. The incremental increase with public Texture2D photoTexture = null; is much smaller but still happens.

I tried putting the code inside TestTextureWork() in a while loop with a bool to make it run once and tried photoClassList.Clear() at the end but neither solved it.

What is the reason I am getting so much memory use (especially with new Texture2D(500,500);) and why is texture memory incrementally being used more and more the more times I run this? It seems like there is a lot of data being persistently created in the memory and never cleared. How would I clear all this data as I go?

Basically, what am I doing wrong? Is there a correct way to initialize variables or make temp lists/variables that doesn’t cause persistent memory use? Or how would I manually best clear things at the end in the example above?

Thanks for any help or guidance.

Whenever you create an Object that derived from UnityEngine.Object you are 100% responsible for it’s lifetime and thus need to destroy it when no longer needed.

In your case you will need to Destroy the Texture2D when done with the instances.

1 Like

Thanks Spiney. I didn’t know that. That makes sense. I didn’t realize Texture2D objects will live forever if I don’t destroy them.

But I am not sure how to do this.

I tried cleaning up the code with Object.DestroyImmediate but now it destroys the texture assets (images) in Unity so after running I needed to Reimport them.

I then tried setting them to null but that prevented anyone else from loading those resources after (ie. it nulled the photo1, photo2, etc. so no one else could get them either).

What is the correct way to get the Texture2D objects out of memory?

As Unity objects live in both C# and C++ they’re managed, or better put, you are the manager. You decide how they live and die. When you Instantiate and Destroy game objects you’re essentially doing that.

I did see your previous post before you deleted it. If you’re getting warnings about using Object.Destroy then it sounds like you were trying to destroy assets?

As it stands, you’re loading already existing assets, thus no need to new Texture2D(), and should none of those images eventuate to null then that line of code isn’t even being called.

1 Like

Thanks Spiney. Yeah, I’ve been sitting here testing code trying to figure out what I’m supposed to be doing and thinking something is working then finding out it isn’t.

I think you explained part of the problem I am having.

If I say Texture2D newTexture = new Texture2D(500,500) then there is no harm in destroying that later or setting it to null. ie. Any of:

Object.Destroy(newTexture);
Object.DestroyImmediate(newTexture,true);
newTexture = null;

However, if I say Texture2D newTexture = Resources.Load(“photo1”) and then destroy that later or set it to null, it prevents me from accessing that photo1 asset anywhere else in my code after that. Ie. It nulls out or destroys the asset itself. With Destroy/DestroyImmediate I have to afterwards Reimport photo1 to make it work again.

So I guess I have to be careful how I am handling Textures. If I create one from scratch, they seem to take an enormous amount of memory, and I can freely destroy it when done. If I am using Resources.Load to access it, I cannot destroy or null it when done.

If you’re making a new Texture2D you should destroy it when no longer needed.

Destroy is for runtime use and should not be used on actual assets.

DestroyImmediate is for Editor use and can destroy assets. You don’t want to be using this in your situation.

Nulling the reference will still leave the Object floating in memory.

As mentioned Resources.Load returns the actual asset either in the editor’s asset library or in a built game’s resources file. You do not want to be destroying these.

However due to the nature of Resources, dereferencing the asset also won’t eventually clear it from memory. Assets loaded via Resources will stay in memory until specifically told to unload (I should have mentioned this earlier sorry).

So I would look at the unload methods in Resources, or use other ways to reference your assets. Personally I’d just use a scriptable object with a List<Texture2D>.