Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question Addressables newb - Is it alright to release an addressable asset immediately after loading it?

Discussion in 'Addressables' started by qtran122, Sep 23, 2022.

  1. qtran122

    qtran122

    Joined:
    Dec 16, 2013
    Posts:
    6
    I have a 2D game where I will swap out the background parallax art as the player moves between areas. This code to swap out the background sprite seems to do the trick:

    Code (CSharp):
    1. private static void LoadBigBackGroundSprite(string addressable_name, SpriteRenderer sprite_renderer_to_set) {
    2.         AsyncOperationHandle<Sprite> handle = Addressables.LoadAssetAsync<Sprite>(addressable_name);
    3.         handle.Completed += handle_op => SetSpriteWhenDone(handle_op, sprite_renderer_to_set);
    4.         handle.WaitForCompletion();
    5.     }
    6.  
    7.     private static void SetSpriteWhenDone(AsyncOperationHandle<Sprite> handle_op, SpriteRenderer parallax_sprite) {
    8.         if (handle_op.Status == AsyncOperationStatus.Succeeded) {
    9.             parallax_sprite.sprite = handle_op.Result;
    10.             Addressables.Release(handle_op); // <-- I can release immediately without consequences??
    11.         } else {
    12.             Debug.LogError("Background Sprite load failed.");
    13.         }
    14.     }
    As soon as I get the sprite I need, I assign it to the dedicated background sprite object, and then release the handle. This appears to work... But from reading the manual (link here), under the section, "Loading by address", they seem to recommend you release the addressable when you "destroy" the object.

    However, the way I'm doing it now appears to work just fine? The background sprite is never destroyed (I have a one scene game - I just swap the sprites). Also, if I release the handle immediately, I don't have to worry about storing the handle to be released later. So it appears to work and is more convenient...

    Are there any consequences to doing it the way I'm doing it?
     
  2. LuGus-Jan

    LuGus-Jan

    Joined:
    Oct 3, 2016
    Posts:
    169
    From my own experience, it works fine until it has to load something again. This won't happen for a single sprite, but in the case of a prefab, for example, where you have some nested game objects that are inactive initially. If you load the prefab through addressables, instantiate it, then destroy the loading handle, and some frames afterwards set those nested game objects active, then the assets that these game objects needs are not available in memory to show. So any textures or meshes in those nested objects won't show up, or the material will show the iconic pink color.
     
    qtran122 likes this.
  3. qtran122

    qtran122

    Joined:
    Dec 16, 2013
    Posts:
    6
    Thanks Lugus!

    If you don't mind a couple follow-up questions...

    "This won't happen for a single sprite"


    So does that mean my use case, which does just load single sprites, is okay? Or is it theoretically unsafe?

    "If you load the prefab through addressables, instantiate it, then destroy the loading handle, and some frames afterwards set those nested game objects active, then the assets that these game objects needs are not available in memory to show."

    I think I'm using addressables in a very simple manner (basically just want to replace my Resource.Load calls). For instance, when I load asset/instantiate a boss monster prefab, it's because I plan to make use of the boss right away. So I wouldn't wait some frames before making the boss active - the boss would immediately become active in the LoadAsync callback. If that's how I plan to use it, does your warning still apply?

    Or does the boss monster being active in the scene sorta act as a "reference", and so any textures the boss was using wouldn't be allowed to disappear?
     
  4. LuGus-Jan

    LuGus-Jan

    Joined:
    Oct 3, 2016
    Posts:
    169
    I think it's safe if the sprite is immediately displayed.

    As long as your prefab has all the resources it requires be active during instantiation, it should be fine. But like I said, if you have anything that is inactive that becomes active later, or perhaps some particle effects (these might be some edge cases you could run into later down the line), it might run into trouble.

    Most of what you currently want seems to be undefined/undocumented, and possible unintended behaviour. My answers above are based on my own brief testing and debugging. It's something that could change between Unity version updates or Addressables version updates. It might work for now, but could also break further down the line.
     
    qtran122 likes this.
  5. qtran122

    qtran122

    Joined:
    Dec 16, 2013
    Posts:
    6
    I see... I guess it's not much more work to just keep the handles and release when advised.

    Thanks again for your help!
     
  6. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    6,008
    From experience, yes you can release the handle once you have a reference to the loaded asset. This will keep it in memory, while addressables knows that it doesn't need to hold onto the asset. Once the asset is no longer referenced it should be cleared from memory.

    I haven't experienced any issues with nested prefabs, but I don't exactly use prefab all that much.
     
    qtran122 likes this.
  7. Midiphony-panda

    Midiphony-panda

    Joined:
    Feb 10, 2020
    Posts:
    235
    I would have thought the following : if the internal Addressables reference counter gets to zero after an Addressables.Release, the asset would get unloaded anyway, even if there is still a remaining C# reference to the Managed Object representation of the asset.

    Did I understand wrong ? (aside from the assets packing strategy, like mentioned here)
     
  8. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    6,008
    No and no. Addressables isn't going to just null references out from under you, that would be terrible. And managed objects - unless destroyed - will exist in memory while there is a C# reference to them in play.

    My general pattern is: load local reference, release handle, use local reference. Always works.
     
    gooby429 likes this.
  9. oBlissing

    oBlissing

    Joined:
    Oct 2, 2017
    Posts:
    10
    This has not been my experience when trying out Addressables the last few days. It is definitely nulling out references from under me (mostly ScriptableObjects that are referenced inside the Addressable prefab I'm releasing from memory, but anyway), and it is indeed terrible. Maybe I'm doing something wrong.

    Do you care to expand on this? Most documentation and other threads I'm finding says "release it when you're done with it".
    When I'm trying to release the handle directly after loading a local reference to the GameObject loaded I get two errors:
    *
    Assertion failed on expression: 'm_PreventLoadingFromFile != nameSpaceID'

    *
    UnloadAssetBundle failed
     
  10. gabrimo

    gabrimo

    Joined:
    May 2, 2015
    Posts:
    86
    I endorse that, at least with Scriptable Objects, the references get null on build mode (Play mode script: Use existing build) if you release the handle and happen to need the loaded reference afterwards. I'm trying to come up with a solution for that, but I'm not that experienced or prepared to do so. For now, my first measure is to have a simplified version of the most numerous SOs on my project, which only has a couple of basic data about it like title, ID and etc. This way I can load a bunch of them without consume all resources...
     
  11. Apex_Dev_03

    Apex_Dev_03

    Joined:
    Aug 18, 2023
    Posts:
    3

    I have seen this error before when an asset bundle had a camera with a render texture assigned. We made sure to remove all references to the render texture and remove it from the asset bundle in order to fix the error.