Search Unity

Memory is never freed

Discussion in 'Scripting' started by RakNet, Aug 8, 2021.

  1. RakNet

    RakNet

    Joined:
    Oct 9, 2013
    Posts:
    315
    I load a scene unload that scene back to the main menu. The textures used in that level persist in memory. For example, you can see Cow_Albedo in the 2nd column. The cow is only referenced in that scene. I thought this was an editor only issue, but it's happening in the player too. I am calling
    Resources.UnloadUnusedAssets();
    System.GC.Collect();

    Huge problem because eventually players run out of memory and crash.

    What is going on here?

    upload_2021-8-7_21-29-15.png
     
  2. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    Are you sure no references exist? ScriptableObjects, prefabs, nothing?
     
  3. RakNet

    RakNet

    Joined:
    Oct 9, 2013
    Posts:
    315
    There's no explanation for it. I stripped down the prefab to the animator and the LOD Group and the issue still occurs.
     
  4. ADNCG

    ADNCG

    Joined:
    Jun 9, 2014
    Posts:
    994
    @RakNet Right clicking the asset in the project view -> Find refs in scene returns absolutely nothing in the hierarchy search?
     
    RakNet likes this.
  5. RakNet

    RakNet

    Joined:
    Oct 9, 2013
    Posts:
    315
    Wasn't aware this feature existed, it pulls up my class that manages addressables.

    I load the scene without the cow, no cow texture in memory.
    I pause the game, put the cow in the scene in the editor, delete the cow, and call GC.Collect. Cow texture is still in memory
     
  6. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    How does your class that handles addressables work? Any reference at all to the asset will load it in memory, even if it's not in the scene. If you had a "Bullet Factory" GameObject with every bullet prefab linked, every asset related to those bullets will be loaded, even if you haven't created a single bullet.
     
  7. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,005
    GC.Collect is only a function of the Mono / .NET framework. Unity is a C++ engine. When you create UnityEngine.Object derived objects they usually need to be destroyed when they are no longer used. Certain objects are destroyed automatically when a new scene loads, though not all of them. However Unity has the method Resources.UnloadUnusedAssets which is similar to GC.Collect but does actually destroy assets which are currently not used by any object in the scene. AFAIK this is implicitly called when a new scene loads.
     
    GroZZleR likes this.
  8. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,460
    This is by design. An explicit UnloadUnusedAssets call after the menu scene was loaded or loading an empty scene in-between or a scene unload with an explicit UnloadUnusedAssets option passed in would cause the native resources to unload, otherwise they will only unload on the next scene unload.

    With those, it is not, though I would call these in the opposite order and make sure the GC pass finished via GC.WaitForPendingFinalizers();

    In the Memory Snasphot you took, have you selected a texture you do not expect to see anymore and clicked on the blue number in the References column? This should tell you what is directly referencing it and keeping it in memory. You can click through the reference numbers of these entries too to investigate the reference tree.
     
    Jonas-Neuston and Bunny83 like this.