Unloading an old asset after loading a new asset

Update: Please ignore the first post and scroll down to read the last post in this thread. I think I found a memory leak in Addressables.

I have a list of large materials and I only need to use one of them at any given moment. Every time I need to switch to a new material, I load the new material with Addressables.LoadAssetAsync() and release the previous one with Addressables.Release(), like this:

private AsyncOperationHandle<Material> handle;
...
private IEnumerator LoadNewMaterial()
{
// Unload the old material:
            if(handle.IsValid())
            {
               Addressables.Release(handle);
               Resources.UnloadUnusedAssets();
            }

// Load the new material:
            handle = Addressables.LoadAssetAsync<Material>(materialRef);
            yield return handle;

            if(handle.Status == AsyncOperationStatus.Succeeded)
            {
                material = handle.Result;
            }
}

It works but there’s a brief moment, until the new material is loaded, where I can’t show any material since the previous one has just been unloaded. I want to avoid not being able to show any material and I don’t want to keep more than 1 material loaded for more than a few seconds (at most). Any idea how this can be done?

I tried to keep a reference to the result but that won’t prevent the material from being unloaded once the handle is released.

I guess I can try using 2 different handles but that would make the code too cumbersome.

Maybe this video can make it easier to understand the problem. Here’s an example of what I’m dealing with (notice the pink color):

Except in my project the materials are much heavier so the loading time (when the pink color shows up) is longer. Is there way to switch materials without having to show that pink color and without having to keep both materials loaded in memory?

Update: I found out how to get rid of the pink color but I think there’s a bug in Addressables’ memory management. Take a look at the following code:

private IEnumerator MemoryLeak()
    {
        handle = Addressables.LoadAssetAsync<Material>(materialRef1);
        handle2 = Addressables.LoadAssetAsync<Material>(materialRef2);

        yield return handle;
        yield return handle2;

        if(handle2.Status == AsyncOperationStatus.Succeeded)
        {
            Addressables.Release(handle);
            //Addressables.Release(handle2);
            Resources.UnloadUnusedAssets();
        }
    }

If I build this and run (it might not show you the leak in Playmode) then the profiler clearly shows that the first material is still in memory with a references count of 0. However, if I uncomment Addressables.Release(handle2); then, according to the profiler, both materials are unloaded.

Can anybody confirm it’s a bug? Or am I missing something?

Hi,
To determine what is loaded and what isn’t,
are you using the Addressables Profiler
or the Memory Profiler?

Also:
According to the Addressables Documenation

So while it looks like in our case the Material isn’t unloaded unless everything in the bundle is no longer ref counted, that does clash with he documentation so this could be a bug in the Addressables system. I don’t know it enough to be sure though. Maybe double check that Addressables Documenation page I linked to, double check your dependencies and ref counts and then report a bug if everything seems to be in order?

@MartinTilo - thanks for your reply! I was referring to the Memory Module of the built-in Unity Profiler (I used the “Detailed View” and then clicked the “Take Sample” button to get a list of all the assets loaded in memory). I am referring to a situation where I explicitly call UnloadUnusedAssets() but the asset won’t unload, even though the ref count is 0 (according to the profiler). I’ve also read that document you linked to while trying to figure out that problem but it doesn’t seem to help much. I guess I’ll report this as a bug then.

BTW, I can’t find the Addressables Profiler in the last stable version, There’s no option called “Addressable Profiler” in Window > Asset Management. Maybe it was discontinued.

I think it was discontinued, yes.

1 Like

OK, I think I’ve found a solution to this problem (turns out it’s not a bug after all). According to this link from Unity’s manual:

It also says in this link that:

So, I went to the Addressables Group window (Window>Asset Managements>Addressables>Groups) and I created a new group just for the material I wanted to unload. Now that the material is in a different group it also puts it in a different AssetBundle so I finally managed to successfully unload it from memory.

1 Like