Search Unity

Loading a ScriptableObject multiple times and releasing it

Discussion in 'Addressables' started by AzurySimon, Apr 9, 2020.

Thread Status:
Not open for further replies.
  1. AzurySimon

    AzurySimon

    Joined:
    Jul 16, 2018
    Posts:
    38
    I am trying to load a ScriptableObject using Addressables:

    Code (CSharp):
    1. public AssetReference myReference;
    2. private MyScriptableObject loadedObject;
    3.  
    4. private void OnEnable()
    5. {
    6.     myReference.LoadAssetAsync<MyScriptableObject>().Completed() += OnLoadComplete;
    7. }
    8.  
    9. private void OnLoadComplete(AsyncOperationResult<MyScriptableObject> obj)
    10. {
    11.     loadedObject = obj.Result;
    12. }
    13.  
    14. private void OnDisable()
    15. {
    16.     loadedObject = null;
    17.     myReference.ReleaseAsset();
    18. }
    This works fine, I can see the asset being loaded and unloaded in the Profiler/Eventviewer.

    Now if I use this same code in multiple scripts or instances of that script, it works: I get the referenced asset, can do stuff with it, everything is fine. The profiler shows the correct number of "instances/references".
    As soon as one of my scripts gets disabled, ReleaseAsset is called, the reference count goes down by one and the asset is still shown in the profiler.
    However when I try to deactivate another one of my scripts (ie call ReleaseAsset) anytime after that, I get a warning:
    Code (csharp):
    1. Cannot release a null or unloaded asset.
    . This is while the reference counter on the asset reference is still not 0 and the loaded asset is still shown in the profiler.

    My questions are:
    - Do I have to build my own manager for loading and releasing ScriptableObjects, so LoadAsset is only called once and ReleaseAsset is only called when my own internal counter reaches 0?
    - Is this a bug? If no, shouldn't calling LoadAssetAsync on an already loaded AssetReference also print out a warning?
    - If this is intended, is there a way to check if a referenced asset is already loaded and access its content right away? If yes, how would that work while the asset is still loading from a call to LoadAssetAsync in another script?
     
  2. TreyK-47

    TreyK-47

    Unity Technologies

    Joined:
    Oct 22, 2019
    Posts:
    1,822
    I'll forward this over to the team for them to check out for you! Which version of the editor and Addressables are you using?
     
  3. AzurySimon

    AzurySimon

    Joined:
    Jul 16, 2018
    Posts:
    38
    Thanks, we are using Unity 2019.3.0f6 (Windows) and Addressables 1.7.5.
     
  4. TreyK-47

    TreyK-47

    Unity Technologies

    Joined:
    Oct 22, 2019
    Posts:
    1,822
    And thank you for flagging! After connecting with the team, turns out this is a bug. They are creating a ticket to investigate.
     
  5. Thermos

    Thermos

    Joined:
    Feb 23, 2015
    Posts:
    148
    I found a walk around. Load and keep one asset in that group in memory(load one audio clip manually before loading scriptable objects referencing to these clips), then everything works as excepted.
     
    Last edited: May 3, 2020
  6. AzurySimon

    AzurySimon

    Joined:
    Jul 16, 2018
    Posts:
    38
    Thanks!

    I am not sure I understand.. Since I do not necessarily know what assets are themselves referenced by my ScriptableObject, I would have a hard time preloading one of those. If you mean keeping a reference to something from the loaded ScriptableObject: we tried that, did not work.

    As a workaround we actually built a small utility script with its own counter, through which we currently load all AssetReferences, as I described in my original post. It keeps track of loaded AssetReferences and only actually calls LoadAsset the first time it is requested. ReleaseAsset is also only called once when all scripts who previously requested the reference have released it again.
     
  7. Thermos

    Thermos

    Joined:
    Feb 23, 2015
    Posts:
    148

    Strange, I was doing exactly what you described. We use scriptable objects to reference some audio clips. We split them into two different groups, one is for these scriptable objects, one is for all clips they are referencing.

    What happened to me is load the scriptable object for the first time, and only once, because we have our own ref counter, everything is fine. Quit to start menu, so we unload all scriptable objects. When we load them again, all reference to audio clips are lost. But if we load one random audio clip from Group B at the beginning of the game and never unload it, everything works. That is what I mean by "Keeping a referencing".

    Seems these are two similar but different bugs, I will see if I can get a minimum repo project for bug reporting.
     
  8. AzurySimon

    AzurySimon

    Joined:
    Jul 16, 2018
    Posts:
    38
    We are using the system a bit differently. We do not have a group of assets separate from the ScriptableObject, we rely on the system working out dependency for us. This seems to work since the assets referenced in the ScriptableObjects are never referenced anywhere else and therefore get excluded from the "normal" build. So we just have the ScriptableObject as an AddressableReference. Its that we can just never unload this ScriptableObject as soon as we load it from multiple scripts. Releasing the asset "works" once, ie it decreases the reference counter in the addressable system, but any subsequent calls to Release do nothing, meaning the AssetReference will never actually be removed from memory.
     
Thread Status:
Not open for further replies.