Search Unity

Addressables.LoadSceneAsync/UnloadSceneAsync Memory Leaks

Discussion in 'Addressables' started by BellyLand, Sep 21, 2019.

  1. BellyLand

    BellyLand

    Joined:
    Feb 5, 2019
    Posts:
    6
    Basically, I've used LoadSceneAsync/UnloadSceneAsync to load/unload many scenes at runtime.
    For the context:
    My problem is that, at runtime, the memory wasn't cleaned up properly and when I look at the memory section of the profiler, the amount of mesh keep increasing every time the scene is loaded, but when the scene is unloaded the meshes doesn't get released. (The GfxDriver memory section also show memory usage increasing all the time as the consequences)

    Seems like the UnloadSceneAsync doesn't clean up all the Assets (meshes) associated with the loaded scene, and later when loading the same scene again with LoadSceneAsync, another copy of meshes get allocated again, and the loops goes on leaking more and more memory.

    My problem seems similar to this issue:

    The code that i use to Load/Unload the scene is basically this, but load/unload scenes based on distance to the camera instead:
    Code (CSharp):
    1. void OnButtonClick()
    2.     {
    3.         if(string.IsNullOrEmpty(addressToAdd))
    4.             Debug.LogError("Address To Add not set.");
    5.         else
    6.         {
    7.             if (m_ReadyToLoad)
    8.                 Addressables.LoadSceneAsync(addressToAdd, LoadSceneMode.Additive).Completed += OnSceneLoaded;
    9.             else
    10.             {
    11.                 Addressables.UnloadSceneAsync(m_LoadedScene).Completed += OnSceneUnloaded;
    12.             }
    13.         }
    14.     }
    15.  
    16.     void OnSceneUnloaded(AsyncOperationHandle<SceneInstance> obj)
    17.     {
    18.         if (obj.Status == AsyncOperationStatus.Succeeded)
    19.         {
    20.             textArea.text = "Reload " + addressToAdd;
    21.             m_ReadyToLoad = true;
    22.             m_LoadedScene = new SceneInstance();
    23.         }
    24.         else
    25.         {
    26.             Debug.LogError("Failed to unload scene at address: " + addressToAdd);
    27.         }
    28.     }
    29.  
    30.     void OnSceneLoaded(AsyncOperationHandle<SceneInstance> obj)
    31.     {
    32.         if (obj.Status == AsyncOperationStatus.Succeeded)
    33.         {
    34.             textArea.text = "Unload " + addressToAdd;
    35.             m_LoadedScene = obj.Result;
    36.             m_ReadyToLoad = false;
    37.         }
    38.         else
    39.         {
    40.             Debug.LogError("Failed to load scene at address: " + addressToAdd);
    41.         }
    42.     }
    My current solution is to use Resources.UnloadUnusedAssets() to manually unload the unused assets, which seems kind of hacky. So I was wondering if there is a
    better way to handle this issue? Is there a better way that I can release those specific assets associated with the specific scene so it doesn't leak? Is this a bug or is this an expected behavior?
     
  2. Favo-Yang

    Favo-Yang

    Joined:
    Apr 4, 2011
    Posts:
    464
    Probably caused by the fact that you cannot partially unload an asset bundle, see docs.

    Workaround, change group pack mode to something smaller scale - like pack separately.
     
    RecursiveFrog likes this.
  3. BellyLand

    BellyLand

    Joined:
    Feb 5, 2019
    Posts:
    6
    Thanks for replying, for the other addressable assets types that seems to be true, but for some reason I feel like the assets (mesh/texture) that get automatically loaded by addressable scene asset behave differently than normal addressable assets. Because I can't specifically called LoadAsset/ReleaseAsset on them, I don't have the explicit control to their life-time. I only have control to the scene load/unload API, which should theoretically handle all the life-time of its dependent assets correctly, but it has failed me and leaks memory.
    Quoting @unity_bill in this [unity forum]:
    • "Textures and meshes, on the other hand, do not get flattened into the scene. So if you marked a texture from a scene as addressable, the scene will point to the texture that got pulled into its own bundle"

    So he seems to be saying that when loading the addressable scene, all the mesh/texture will be loaded from their bundle (new native mesh/texture instance from that bundle). But the lifetime of those mesh/texture assets are unclear to me, those assets doesn't show up in Addressable Profiler at all, so I'm not even sure if its really being loaded from its bundle or it get flatten into the scene (but probably not being loaded through Addressable API internally right? since it doesn't show up in Addressable Profiler).
    • The only things I know is that it leak memory, where every time the same addressable scene is loaded, the new native mesh/texture instances is created, and unloading the scene doesn't clean it up. (leaving a lot of the same mesh/texture copies overtime)
    • I even try unloading all the addressable scene that's supposed to unload all the mesh asset from their bundle (hence the bundle should be unloaded), but all those mesh instance still isn't being released and is still leaking. So I don't think grouping those assets into smaller pack will work, since when the bundle is (should be) unloaded, the mesh doesn't really get released. But I will try anyway and update later.
    I'm still learning about Addressables stuff, so if I says anything wrong, please educate me.
     
  4. Favo-Yang

    Favo-Yang

    Joined:
    Apr 4, 2011
    Posts:
    464
    Then, you can report a bug to Unity, better with a minimal reproducible repo. Just put one scene into a group (pack to a bundle), and load one mesh in that scene. Then try load / unload the addressables scene, and monitoring the memory changes.
     
  5. skwsk8

    skwsk8

    Joined:
    Jul 6, 2014
    Posts:
    36
    We seem to be running into this issue as well. We have the addressable scenes packed separately and are using Addressables.UnloadSceneAsync, but are getting memory leaks. Has there been any investigation/update?
     
  6. matt_unity455

    matt_unity455

    Joined:
    Sep 25, 2019
    Posts:
    6
    We are also having issues with this and would appreciate any input.

    Edit : Update to this - even trying to load and unload the most simple of scenes (with a couple of sprites) still results in a memory leak. Are we missing something obvious?
     
    Last edited: Dec 30, 2019
    ROBYER1 and skwsk8 like this.
  7. cg-adam

    cg-adam

    Joined:
    Jul 30, 2019
    Posts:
    44
    We are seeing these issues as well. I have heard this is being used in shipped titles, but it would seem the most simple of API interactions can cause memory leaks which is baffling me. Any guidance on this would be great @unity_bill
     
    fmodesto and skwsk8 like this.
  8. Joshdbb

    Joshdbb

    Joined:
    Oct 28, 2014
    Posts:
    50
    I just encountered an issue where the scene asset bundles weren't being unloaded when I loaded a new scene.

    I seem to have fixed the issue by holding onto a reference to the 'AsyncOperationHandle' that was returned when I called 'Addressables.LoadSceneAsync'. Then when I load the next scene I call 'Addressables.Release' on the handle and all of the bundles unload as expected.
     
  9. CameronND

    CameronND

    Joined:
    Oct 2, 2018
    Posts:
    89
    I also enountered this. I thought that if I loaded a scene using Addressables.LoadSceneAsync, then the next call to load a scene (either using addressables or SceneManager) should automatically unload the scene bundle for me shouldnt it?
    Even calling Resources.UnloadUnusedAssets doesn't seem to free the scene bundle for me.

    Is the only solution to track the handle ourselves and explicitly call handle.Release manually? Surely this can be detected and automated upon changing scenes....
     
  10. ProtoTerminator

    ProtoTerminator

    Joined:
    Nov 19, 2013
    Posts:
    586
    Oh, does the system not automatically clean up scenes that are unloaded from a LoadSceneMode.Single? I read that it automatically cleans up GameObject instances that are destroyed with a scene, so I assumed it did the same with the scenes themselves, and wrote my asset manager assuming that... guess I'll have to go rewrite that now.
     
  11. CameronND

    CameronND

    Joined:
    Oct 2, 2018
    Posts:
    89
    I am still trying to figure it all out, but it looks like it does unload any bundles that are loaded in with the scene as dependencies, but the scene bundle itself doesnt get unloaded when changing scenes.

    I'm still learning how the addressables system works so maybe I am just misunderstanding what the event view is showing me. Please let me know if you notice the same thing.
     
  12. davidla_unity

    davidla_unity

    Unity Technologies

    Joined:
    Nov 17, 2016
    Posts:
    763
    Has anyone submitted a bug regarding this through the bug reporter? That would go a long way in helping us track down this issue.

    We did fix one issue regarding unloading scenes in 1.6.3 which should be out before too long. I'm not sure if it's causing the issues reported here but it might be worth checking out in the meantime.
     
  13. cg-adam

    cg-adam

    Joined:
    Jul 30, 2019
    Posts:
    44
    We will test once 1.6.3 is out and see if we are still seeing similar issues. Will try and submit a report when we can if it still persists, quite a large project right now.
     
    davidla_unity likes this.
  14. Xeethrax

    Xeethrax

    Joined:
    Feb 17, 2013
    Posts:
    10
    @cg-adam did you figure it out? I'm running into the same issue, almost a year later :) I did something similar to TS, created a fresh project to experiment with, and found that meshes and textures are not being released properly after unloading a scene. I've tried all possible ways to group assets, with and without pack separately, in different versions of Addressables, including 1.19.17 and both 2020 LTS and 2021.2. I tried with different play mode scripts, with/without building the bundle. All same results.
    Also fairly new to Addressables, also worried I might have missed something fundamental. But it shouldn't be this hard to do it "the right way".
    This is the result of loading/unloading the first couple of times. I also looped it 100 times and had the same keep happening without anything getting freed at any point. I especially like the part where unloading actually increases texture memory.


    Edit: I also posted a bug report, #1394563
     
  15. etliaojing

    etliaojing

    Joined:
    Feb 5, 2014
    Posts:
    4
    Looks like this line of code in the unloading logic causes the memory leak:
    Code (CSharp):
    1. m_LoadedScene = new SceneInstance();
    Every time a scene completes unload, it creates a new SceneInstance, which soon becomes unmanaged while loading a new scene. You don't need to handle the releasing since Adressable.UnloadSceneAsync already handles that (unless you are setting the autoReleaseHandle to false).

    This official tutorial shows a minimal happy path to load/unload an addressable scene (it caches the AsyncOperationHandler):
    https://learn.unity.com/tutorial/addressables-scene-loading#

    In general, the AsyncOperationHandle, by default created from the addressable async operation, is UNMANAGED in terms of C#'s GC. In my code, I always double check if it is correctly released after used. Hope it could help on the memory leaking issues here.
     
  16. Glader

    Glader

    Joined:
    Aug 19, 2013
    Posts:
    456
    I'm also encounteed a memory leak in Addressables 1.20.0 in Unity3D 2022.1.20f1

    The memory profiler showed continued increased memory usage in the Object Stats after loading and unloading an addressable scene.

    The solution I found was to methodically track resource load operation handles and then call Addressables.Release on all of them after unloading my addressable scenes. I think it's also important to cache and reuse these handles when loading the same resource multiple times during the scene load. However, I am abit worried this will endlessly consume memory if you never change scenes. So I think a lot of care needs to go into tracking and managing these handles to avoid both memory leaks and long-term memory usage.