Search Unity

Release Asset vs Release Instance

Discussion in 'Addressables' started by Allan-Smith, Jul 15, 2018.

  1. Allan-Smith

    Allan-Smith

    Joined:
    Feb 7, 2012
    Posts:
    57
    Hi,

    Sorry if this is answered elsewhere but I couldn't find it in the docs or the forum. Say I load an scriptable object by doing
    var operation = Addressables.LoadAsset<ScriptableObject>(address)
    , then grabbing its reference by
    var reference = operation.Result
    . In this scenario, I imagine that the right way to unload this object is by calling
    Addressables.ReleaseAsset(reference)
    , right?

    However, what if this is a prefab. Say I load it through Addressables, then I go on to populate a pool with 100 instances of it. Then, I leave the scene where the pool is used so I want to clean it up. If I call ReleaseAsset, will this destroy the 100 instances? Do I need to call ReleaseInstance for each of the instances AND THEN ReleaseAsset? Whats the correct way to go about this?

    Best,
    Allan
     
    lucbloom, FlightOfOne and amesa_unity like this.
  2. Kichang-Kim

    Kichang-Kim

    Joined:
    Oct 19, 2010
    Posts:
    1,011
    You should use Addressables.ReleaseInstance() only for instance which created by Addressables.Instantiate().

    If you populate instances via GameObject.Instantiate(), instances are not destroyed by calling Addressables.ReleaseAsset() because Addressables does not have any references to it.
     
    sohamxbr, lucbloom and Perturbator858 like this.
  3. james7132

    james7132

    Joined:
    Mar 6, 2015
    Posts:
    166
    According to the (currently sparse) documentation, you can use Addressables.ReleaseInstance as a replacement for Object.Destroy. If the instance isn't managed by Addressables, it just destroys the object. If it is, it decrements the reference counter for the source asset.

    Though on this topic, I do wish to ask: what happens to instantiated objects destroyed by other means: i.e. scene loads? It would be nice to have an Addressables equivalent to Resources.UnloadUnusedAssets that runs through the list of managed references and cleans up instances that were destroyed by some other mechanism.
     
    Last edited: Aug 7, 2018
    Kichang-Kim likes this.
  4. Allan-Smith

    Allan-Smith

    Joined:
    Feb 7, 2012
    Posts:
    57
    Yes, I understand that. The question is... if I ReleaseAsset on an asset used in 100 instances instantiated with Addressables.Instantiate, are all 100 instances destroyed to free the memory or does it just not work?
     
  5. unity_bill

    unity_bill

    Joined:
    Apr 11, 2017
    Posts:
    1,053
    @Allan-Smith -
    Two bits of context before I get to the answer. First, ignoring Addressables and looking a little lower-level. If you load an asset from an asset bundle, instantiate it, then unload the asset and the bundle, you are in an uncertain situation. Some things are fine after being instantiated and some are not. Say your prefab references a texture from that bundle. Unloading it will break the live-link to that texture. So unloading a bundle post-instantiation is does not guarantee disaster, but is unlikely to be a good idea.

    Second bit of context, you have two choices for your instantiating:
    1. If you do Addressables.LoadAsset("x"), then take the result and Instantiate it 100 times, our ref count on "x" will be 1.
    2. If you do Addressables.LoadAsset("x"), then Addressables.Instantiate("x") 100 times, our ref count on "x" will be 101.

    Now, to answer your question. If you do Addressables.ReleaseAsset("x"), you will decrement the ref count by one. In the first scenario, this means the count goes to 0, and the bundle will be unloaded if there's no other still-referenced asset in it. If you are in the second scenario, our ref count will still be at 100, and won't go down until you've called Addressables.ReleaseInstance 100 times.

    Of note, if you put 100 instances into a scene, then close the scene, this is the same as calling ReleaseInstance on those 100 items. We detect the close and react properly.

    So what should you do? Instantiate yourself vs using our API? That's up to you. If you choose to do scenario 1, you need to keep up with your own instance count, and not unload until your instances are gone. If you choose the second scenario, then you could call unload right after instantiating, or potentially never call Load. The only reason to call LoadAsset in the second scenario is if you want to have a loading screen at one point, and not fill in your pool until later.

    Hope this helps,
    Bill
     
  6. Kichang-Kim

    Kichang-Kim

    Joined:
    Oct 19, 2010
    Posts:
    1,011
    @unity_bill
    How about @james7132 's question? If I destroy the gameobject from Addressables.Instantiate() by using norma GameObject.Destroy() or new scene loading, what happen? I think reference still exists but actual object is destroyed, so reference leak occur?
     
  7. Allan-Smith

    Allan-Smith

    Joined:
    Feb 7, 2012
    Posts:
    57
    This does help a lot! Thanks for the answer, that was what I was looking for and it makes sense, kind of what I expected would be the case.
     
  8. unity_bill

    unity_bill

    Joined:
    Apr 11, 2017
    Posts:
    1,053
    If you do Addressables.Instantiate, then clean up with GameObject.Destroy, we will not know about it, and the ref count will not go down. So that's bad. If you do Addressables.Instantiate, then close the scene that thing is in, we do notice that, and decrement ref counts accordingly. So that's good.

    -Bill
     
    antonio_iliev likes this.
  9. james7132

    james7132

    Joined:
    Mar 6, 2015
    Posts:
    166
    Wait so scene unloading does indeed decrement the reference counter (provided we instantiated it with Addressables)? That's not very apparent that is the case from any part of the current documentation.
     
  10. unity_bill

    unity_bill

    Joined:
    Apr 11, 2017
    Posts:
    1,053
    I've made a note to add this to our documentation.
     
  11. cruelbob

    cruelbob

    Joined:
    May 26, 2014
    Posts:
    20
    @unity_bill Does this system counts assets referenced from components? Example:
    I have two different windows (2 different prefabs) using same background. Background is texture used in Image component (see uploaded screen).
    Would texture be unloaded if I unload one of windows?
     

    Attached Files:

  12. unity_bill

    unity_bill

    Joined:
    Apr 11, 2017
    Posts:
    1,053
    "Yes" to your general question, but "we don't count that texture" would be the more detailed answer....

    - if you have 2 parents, referencing the same other-thing. Load both, that other-thing has a ref-count of 2. Unload one parent, and that other-thing now goes down to one and does not get unloaded.
    - BUT, I want to clarify what exactly we're counting. Your prefab has a direct reference to the texture (more likely a direct reference to a material, which then references the texture). This uses Unity's core loading system, not Addressables. As such, we don't actually ref-count that, it just works. The better example would be if those two prefabs came from the same asset bundle. We'd load and ref-count that bundle, then we'd load the prefabs. The objects that Unity loads into memory are correctly managed internally. If in this example, the prefabs were in one bundle, and the texture another, we'd still count the bundles correctly to ensure nothing gets unloaded out from under you.

    Hope that helps,
    -Bill
     
    KwahuNashoba and antonio_iliev like this.
  13. cruelbob

    cruelbob

    Joined:
    May 26, 2014
    Posts:
    20
    @unity_bill How to find out that some texture used by another prefabs? It turns out that we can't unload any prefabs because this can break other prefabs.
     
  14. unity_bill

    unity_bill

    Joined:
    Apr 11, 2017
    Posts:
    1,053
    You don't have to. You load a prefab that requires a texture, Unity loads that texture. You then do that again with another prefab, Unity deals with it. Unload one of the prefabs, and Unity manages everything. If the texture is in an asset bundle, it's not actually unloaded from memory until the bundle is unloaded anyway. Which addressables manages.

    -Bill
     
    FlightOfOne likes this.
  15. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    @unity_bill I'm curious about how careful I need to be in cleaning up my assets. I generally have a lot functionality that can Destroy() a GameObject in my game. You said that Destroy won't clean up the Addressables, but that loading a new scene will clean things up. So, what happens if I Destroy some game objects, and then later I change scene? Will the bundles I loaded get cleaned up at that point?

    In my game, I completely unload/change scenes fairly frequently. My scene transition approach first loads a "Loading" scene via SceneManager.LoadSceneAsync with allowSceneActivation = true, then once that's showing I additively load the "real" scene. My hope is that LoadSceneAsync will act as a catch-all, unloading anything I've loaded up to that point, so I don't need to worry too much about unloading things. Is that an accurate description of what LoadSceneAsync will do?

    But that raises another question: What if I don't want to unload a particular bundle when changing scenes? Maybe I have many scenes in a row that use the same stuff. Is there a way to keep LoadSceneAsync from unloading things if I want to keep them loaded through a scene transition?

    I tried looking at the profiler, thinking it would clear things up for me, but it's still not quite clear. Here's the profiler showing a bundle I've loaded at the first blue tick mark. At the second blue tick mark, I completely reloaded the scene. This stops any more stuff in the profile, but the entry never goes away. Is it correct that my bundle was unloaded after the second blue tick? Or does its presence in the list imply it's still loaded?
    upload_2019-1-8_21-49-55.png
     
    Last edited: Jan 9, 2019
  16. Rotary-Heart

    Rotary-Heart

    Joined:
    Dec 18, 2012
    Posts:
    813
    @dgoyette If you need a way to keep assets loaded I would suggest you using an object on
    DontDestroyOnLoad
    scene to load your assets, this way they will not be automatically released under any scene change (you need to manually release them). This is currently the way I'm doing it, which is still working as of 0.5.3

    Don't get me wrong I like that Unity can handle the release by itself, but I love that we can decide when to release assets manually using this approach.
     
  17. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    Thanks. I've been playing around with this a bit more, and I've determined the following to (hopefully) be true:
    • Objects created via Addressables.Instantiate will be destroyed when changing scenes, decrementing the count, and causing asset bundle to be unloaded automatically.
    • However, if I instead use Addressables.LoadAsset to load a prefab, and make copies of the prefab via GameObject.Instantiate(prefab), changing scenes will NOT cause the asset bundle to be unloaded.
    So, if I always use Addressables.LoadAsset, it doesn't seem like the bundles ever get unloaded when changing scenes, and it's up to me to unload them. If I always use Addressables.Instantiate, then I can likely count on the scene load to clean up any asset bundles.

    So my approach now is for each scene to declare which addresses it uses. When loading the scene, I unload any loaded assets that aren't needed by this scene, and LoadAsset any assets I need for this scene. I pipe everything through a single helper method that performs the Addressables.LoadAsset calls, and never use Addressables.Instantiate.

    This feels like a reasonable approach. It means I can preload any assets the scene needs, and I can keep those assets loaded through the scene transition in the event that the same asset bundle is used by consecutive scenes (which is common), only cleaning them up (unloading) when I transition to a scene that doesn't use that asset.
     
  18. unity_bill

    unity_bill

    Joined:
    Apr 11, 2017
    Posts:
    1,053
    yes.

    One additional thing, just for your awareness. You mentioned the potential of calling Destroy on a game object that may have been created by Addressables. One tip I'd suggest is to just replace every GameObject.Destroy call in your game with Addressables.ReleaseInstance(). If you instantiated the thing via addressables, then this will properly clean it up. If you instantiated it via GameObject.Instantiate(), then we'll detect that and just call Destroy for you (not doing any addressables related logic)

    b
     
  19. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    Thanks for the tip. A couple of quick questions on that:
    • Is there any need/concern around framerate when the cleanup occurs? For example, if I ReleaseInstance on something in the middle of gameplay, could that trigger some long-running process that causes hiccups? I'm just wondering if there's any reason to hold off on ReleaseInstance until the end of a scene.
    • Calling ReleaseInstance instead of Destroy feels pretty ugly to me. I understand the reason for it, but it feels weird calling ReleaseInstance on objects that aren't addressable just in case... Do you know if there's any planned expansion to the package API such that packages (like addressables) can hook into different unity built-in events and do something different/extra? This ReleaseInstance call feels like the sort of thing that should maybe just happen when calling Destroy, if only Unity allowed for that kind of behavior.
     
  20. unity_bill

    unity_bill

    Joined:
    Apr 11, 2017
    Posts:
    1,053
    1. framerate - no issues. The main expensive unloading related thing is Resources.UnloadUnusedAssets. We don't call that from Addressables, and would generally recommend you not call it either.
    2. I doubt there will ever be a world where a package could hijack a built in Unity API and modify it's behavior. The engine could add OnWhatever callbacks, but not a wholesale injection into an interface.
     
    glitchers and MNNoxMortem like this.
  21. jonagill_rr

    jonagill_rr

    Joined:
    Jun 21, 2017
    Posts:
    54
    @unity_bill I'm looking into Addressables as a way to get our app's RAM usage down (right now we have a lot of direct object references, so most of the content in the game is loaded at startup). I'm trying to work out what the lifecycle is of an asset loaded through Addressables in order to make sure we set up our systems to use it properly.

    When does this bundle unload happen? Is it immediate, or is there some LRU cache that keeps frequently referenced bundles in memory for a while? The docs mention configuring CacheInitializationSettings, but I can't work out how they're supposed to be used.

    If we release an asset that does still have references to a loaded asset inside of it, when does the bundle get unloaded? For example, let's say we called Addressables.Instantiate() to load a prefab containing a material referencing a texture from a bundle. This loads the bundle, then loads the prefab, material, and texture, and instantiates an instance of the prefab. If we call Addressables.ReleaseInstance(instance) immediately, I'd expect it to destroy the instance and unload the prefab, material, and texture. (Please correct me if I'm wrong here).

    However, let's say I made a copy of the material before unloading. Now we have a copy of the material in memory, which references the texture. This means that the bundle cannot -- and may never -- be unloaded, right?


    I think what I'm craving is something equivalent to AssetBundle.Unload(true), which to my understanding unloads every asset in the bundle, regardless of whether any references currently exist to those assets. If there are no Addressable references to assets in my bundle, I want the system to forcibly unload it, even if some system somewhere is holding onto a sloppy C# reference somewhere. Is this possible with the current system?
     
  22. jonagill_rr

    jonagill_rr

    Joined:
    Jun 21, 2017
    Posts:
    54
    Digging into it more today, it looks like my testing is being confounded by this issue: https://forum.unity.com/threads/textures-are-referenced-after-asset-release.569860/

    Testing on the latest version of Addressables, I'm still seeing textures hang around in the Memory Profiler even after I release all references to the addressable. Hopefully this is fixed in v1.0!

    That said, I imagine that won't fix still won't be equivalent to AssetBundle.Unload(true), since it sounds like Addressables will intentionally keep assets from the bundle loaded until all references to them have been nulled out. Some way to configure the ResourceManager to aggressively unload assets when unloading bundles would be extremely helpful. Otherwise, we're probably going to have to stick with manually loading and unloading AssetBundles on this project.

    Update: I started poking around in the source code, and I can see that the ResourceManager project's AssetBundleProvider does call AssetBundle.Unload(true), which is great! However, since I'm not seeing the bundle actually unload in my tests, I'm guessing that there is some kind of caching happening to prevent the bundle from unloading as soon as all its references are cleared.

    I can see that there is a CachedProvider set up to wrap AssetBundleProvider in that package, but it's in a Samples directory, and I can't see any equivalent code actually initializing the various providers in the Addressables package. If anyone knows where Addressables is doing this initialization, I'd love to know so I can configure the CachedProviders correctly for our project.
     
    Last edited: Jan 29, 2019
  23. unity_bill

    unity_bill

    Joined:
    Apr 11, 2017
    Posts:
    1,053
    quick note, I'm making the comments below based on our working branch. I think most apply to 0.5.3, but some may be still-to-come

    on each group, there are settings for the Bundle Cache Provider Max LRU Count & Age Use that to control if there is an LRU holding on to bundles in memory or not.

    this is for the bundle cache used to hold bundles on-device after download. Has nothing to do with in-memory.

    it decrements them all. If they are all 0, they will be ready to unload. If there is nothing else in that bundle with a ref count greater than 0, the bundle(s) will be unloaded.

    Say you do roughly this (not real code!):
    var op = LoadAsset("myMaterial")
    var obj = op.Result
    MakeACopy(obj)
    ReleaseAsset(obj)

    after that, things will probably go boom. You've told us you're done with the material, so we've decremented both the material and texture. The texture will be pulled form memory, and your copied material will be referencing a ghost.

    Similar situation:
    var op = LoadAsset("somePrefab")
    GameObject.Instantiate(op.Result)
    ReleaseAsset(op.Result)

    If that prefab referenced a texture, we've unloaded it, so the instantiated prefab will be textureless.

    we always use (true). So when our refcount is 0, that thing gets unloaded. Forcibly.

    yup, that's a thing. should be fixed in the next release.
     
  24. jonagill_rr

    jonagill_rr

    Joined:
    Jun 21, 2017
    Posts:
    54
    Ah, I didn't realize that the LRU cache was configured per-group! I'll test that out tomorrow.

    Thanks for the comprehensive response, @unity_bill!

    I'm extremely impressed with what I've seen of Addressables so far, and I can't wait to dig into more of it.
     
    unity_bill likes this.
  25. Alexaroth

    Alexaroth

    Joined:
    Feb 4, 2019
    Posts:
    29
    So I picked up the addressable system and I have a memory leak that I simply can't trace:

    upload_2019-3-27_21-20-17.png


    The code I use to test this:

    To load and instantiate:

    Addressables.LoadAsset<GameObject>(level.PrefabName).Completed += (op) =>
    {
    Addressables.Instantiate(level.PrefabName, new Vector3(0, 0, 0), Quaternion.identity).Completed += (op2) =>
    {
    CurrentLevelPrefab = op2.Result;
    };
    };


    to unload everything I loaded:

    if (CurrentLevelPrefab != null)
    {
    Addressables.ReleaseInstance(CurrentLevelPrefab);
    Addressables.ReleaseAsset(level.PrefabName);
    }



    What am I missing? How is Level1 in the image (which is the level.PrefabName string) still have a reference that leaks?

    Is it that I don't need to do the LoadAsset? That seems to fix it. My understanding was that LoadAsset("x") would load asset "x" into memory and then I could do Instantiate("x") and that would be pretty much instant, and just create 1 clone of asset "x". Am I wrong? Does LoadAsset leak a gameObject when I don't do anything with the result? And the result from LoadAsset cannot be ReleaseInstance()-ed so I'd have to have 2 game objects if I wanna keep track of 1 instance of asset "x" (1 game object to store the asset and another one to store the clone I'd do via GameObject.Instantiate)
     
    Last edited: Mar 27, 2019
  26. caochao88_unity

    caochao88_unity

    Joined:
    May 16, 2019
    Posts:
    26
    the only thing you should do is use Addressables.Instantiate, loading asset operation is included in this api.
     
  27. gsylvain

    gsylvain

    Joined:
    Aug 6, 2014
    Posts:
    104
    Simply highlighting that the implementation changed since this comment.

    Since Addressables 1.3, the documentation says "If you call Addressables.ReleaseInstance on an instance that was not created using the Addressables API, or was created with trackHandle==false, the system detects that and returns false to indicate that the method was unable to release the specified instance. The instance will not be destroyed in this case."

    You could make a DestroyUtil wrapper that first try to ReleaseInstance then fallback to the classic Destroy method.

    Created an instance from Addressables? Use ReleaseInstance.
    Created an instance from classic Instantiate? Use classic Destroy.
     
  28. LeleUnity

    LeleUnity

    Joined:
    Jul 30, 2016
    Posts:
    97
    -Could you explain HOW to detroy objects that have been loaded with addressable but istantiatated with GameObject.Istantiate without memory leaks?

    -Does Scene switch cleans all?

    -are we forced to use Addrressable.Release in order to not have problems?

    -If I use Addressable.Release(GameObject) will destroy all the instances? I don't want to call addressable.releaseinstace 1000 times... how to do it ?
     
  29. LeleUnity

    LeleUnity

    Joined:
    Jul 30, 2016
    Posts:
    97


    Sorry, still not clear...you didn't explain the difference between
    Addressables.ReleaseAsset("x"), and Addressables.ReleaseInstance !!
    What happens if you do Addressables.ReleaseAsset("x") in case 2 ?
    and what happens if we do Addressables.ReleaseInstance in case 1?


    Also: do we need to keep track in a dictionary the loadedAssets so we don't LoadAsset twice?
    We don't want to do that right? or is there any built-in cache system?
     
    Last edited: Jul 12, 2020
  30. LeleUnity

    LeleUnity

    Joined:
    Jul 30, 2016
    Posts:
    97
    @Allan-Smith @unity_bill also I don't understand what are the best practices for releasing an object...I mean,
    should we load an assett only once, keep a reference in Dictionary and then istantiate it when needed? Then we need to release Release it with ReleaseIstance? but how we can check when to Release the asset instead when the ref count is 0 ? we have to check it everyframe or what?

    Or we need to call inside the OnDisable() of an object first Release istance and then Release Asset everytime?? Should we call release Asset everytime we destroy an istance? Could you please explain the best practice set up ?
     
  31. lejean

    lejean

    Joined:
    Jul 4, 2013
    Posts:
    392
    I don't get what the difference is between release instance and destroy?
    What if you just load a addressable prefab to be reused you still have to use release on all instances?

    Code (CSharp):
    1. public AssetReference EnemyRef;
    2. GameObject enemyPrefab;
    3. GameObject enemy;
    4.  
    5. public void LoadEnemy() {
    6. EnemyRef.LoadAssetAsync<GameObject>().Completed += OnEnemyLoaded => {
    7. enemyPrefab=OnEnemyLoaded.Result;
    8. };
    9. }
    10.  
    11. void CreateEnemy(){
    12. enemy = Instantiate(enemyPrefab);
    13. }
    14.  
    15. void Kill(){
    16. Destroy(enemy);
    17. //or
    18. Addressables.ReleaseInstance(enemy);
    19. }
     
  32. ProtoTerminator

    ProtoTerminator

    Joined:
    Nov 19, 2013
    Posts:
    586
    ReleaseInstance
    should be used to destroy objects that were instantiated with
    InstantiateAsync
    .
    Destroy
    is an engine API that existed long before Addressables, and has no way to notify Addressables to decrement its reference count. Addressables developers recommend replacing
    Destroy
    with
    ReleaseInstance
    in all places if you're unsure, as it will fall back to
    Destroy
    if the object wasn't instantiated from addressables.
     
    Havokki likes this.
  33. lejean

    lejean

    Joined:
    Jul 4, 2013
    Posts:
    392
    So the example above would be correct with using destroy then?

    Cause I use addressable to load the prefab in and then instantiate copies from said prefab.
    If I wanted to remove the prefab then you'd use releaseinstance but I basically need that prefab to keep existing for the rest of the game.
     
  34. ProtoTerminator

    ProtoTerminator

    Joined:
    Nov 19, 2013
    Posts:
    586
    Yes using
    Destroy
    with that example is correct. I believe
    ReleaseInstance
    would also work without decrementing the ref count since that object would not have been registered with Addressables, but I'm not sure. That would require testing (or a dev telling us).
     
  35. CaseyYipYip

    CaseyYipYip

    Joined:
    Sep 2, 2020
    Posts:
    4
    I have a feature request: right now I'm using Addressables.ReleaseInstance instead of destroy, as was recommended. However, if I call this method from a disabled object, I get a Coroutine couldn't be started exception. Now I get 'why' it happens, but still, @unity_bill couldn't you make an isActiveAndEnabled check and have some stuff done outside of a coroutine if that returns false? I'd like to be able to create pools of objects that I release when the pooler is disabled.
     
  36. unity_bill

    unity_bill

    Joined:
    Apr 11, 2017
    Posts:
    1,053
    we had looked into creating a generic pooling system, but that wound up being very game-specific. So what a lot of our customers do is write a little wrapper around addressables. Depending on your needs, this could be very light, just doing a delayed release based on time, or much more involved. In either case, it should handle your situation.
     
  37. FlightOfOne

    FlightOfOne

    Joined:
    Aug 1, 2014
    Posts:
    668
    Hello all, I just want to clarify bit further.

    I am clear on how to use:
    Code (CSharp):
    1. assetReference.InstantiateAsync()
    and
    Code (CSharp):
    1. Addressables.ReleaseInstance(handle);

    But I was reading the documentation and stumbled upon this part:
    Let's say I create some instances using the following:
    Code (CSharp):
    1.  
    2.  
    3. AsyncOperationHandle handle = assetReference.LoadAssetAsync<GameObject>();
    4.  
    5. handle.Completed +=(AsyncOperationHandle<GameObject> result) =>
    6. {
    7.       if(hand.IsValid()) //--- ?? Also, is this needed??
    8.        {
    9.            for (int i = 0; i < 100; i++)
    10.             {
    11.                    testGameObjects.Add(Instantiate(result.Result));
    12.              }
    13.         }
    14. };
    15.  
    16.  
    Is this the way to properly destroy these?
    Code (CSharp):
    1.  
    2. foreach (var item in testGameObjects)
    3. {
    4.      Destroy(item); //destroy using the conventional way
    5. }
    6.  
    7. Addressables.Release(handle); //then release the resources
    8.  
    9.  
    And one last question: What happens if I
    Addressables.Release(handle)
    before destroying the created game objects? On my tests it did nothing (as in nothing bad, worked as normal), but maybe something bad will happen later?

    Thanks!! @unity_bill
     
    Last edited: Oct 10, 2020
    Pronotron likes this.
  38. Pronotron

    Pronotron

    Joined:
    Aug 27, 2018
    Posts:
    7

    I have a similar situation. On start I have no idea which addressable's are going to load. Different spawned in game prefabs are referencing same assets.

    The only solution I can find is, if an asset reference GUID is loading for the first time, caching the handle and GUID, and next time loading that asset from cached source. (Another ugly looking solution is keeping reference count and repeating releaseInstance() for that number at the end of the game)

    So I can release each cached AsyncOperationHandle for clearing memory at the game end. There sould be a function to load with AssetGUID and release all instances with AssetGUID. (Addressables 1.8.5)


    Code (CSharp):
    1. private IEnumerator SpawnFromAssetReference(AssetReference reference)
    2.     {
    3.  
    4.         GameObject gobj = null;
    5.  
    6.         if (!obstacleIDs.Contains(reference.AssetGUID))
    7.         {
    8.             obstacleIDs.Add(reference.AssetGUID);
    9.             AsyncOperationHandle op = reference.LoadAssetAsync<GameObject>();
    10.             yield return op;
    11.             obstacleHandles.Add(op);
    12.             gobj = op.Result as GameObject;
    13.         }
    14.         else
    15.         {
    16.             int index = obstacleIDs.FindIndex(obs => obs.Contains(reference.AssetGUID));
    17.             gobj = obstacleHandles[index].Result as GameObject;
    18.         }
    19. //Instantiate
    20.  
    21.     }
     
    FlightOfOne likes this.
  39. khan-amil

    khan-amil

    Joined:
    Mar 29, 2012
    Posts:
    206
    @unity_bill The documentation now says :
    So, is there a new recommended way to handle deletion? Do we have an API to check if an instance was loaded from an addressable, or contains some loaded stuff from an adressable?
     
  40. ProtoTerminator

    ProtoTerminator

    Joined:
    Nov 19, 2013
    Posts:
    586
    Interesting... it looks like the new way is to do this:


    Code (CSharp):
    1. if (!Addressables.ReleaseInstance(obj))
    2. {
    3.     Destroy(obj);
    4. }
     
    wlwl2 and Nehrk like this.
  41. KwahuNashoba

    KwahuNashoba

    Joined:
    Mar 30, 2015
    Posts:
    110
    This is used in official example and, I believe, reason for that is that they instantiate using both
    GameObject.Instantiate
    and
    AssetReference.Instantiate
    through the examples. So this is just to keep it safe.

    What I'm confused is why not just call
    Addressables.Release
    since it is supposed to maintain reference count if it is object tracked by addressables system, or just call Destroy if it is not.
     
  42. kumade

    kumade

    Joined:
    Nov 3, 2016
    Posts:
    52
    Speaking of the newer versions of the Addressables package (I'm using 1.16.19) and to summarize all the above:
    1) InstantiateAsync does LoadAssetAsync internally for prefabs so you don't need to call the latter if you just need an instance of an asset.
    2) ReleaseAsset is being called automatically during a scene unloading so you don't need to call it if you don't want to manually manage asset's releasing.

    @unity_bill is the above seems correct? Also if you load an asset which is not a game object (a texture, material etc) with LoadAssetAsync - are you also freed from manually releasing it (because it will get released on scene unloading) or this automation works only for game objects and you have to call ReleaseAsset manually in this case?
     
  43. PeterBalso

    PeterBalso

    Joined:
    Oct 23, 2021
    Posts:
    7
    I'm wondering the same thing, if you ever found an answer for this!
     
  44. pillakirsten

    pillakirsten

    Unity Technologies

    Joined:
    May 22, 2019
    Posts:
    346
    @kumade @PeterBalso

    1) Yes correct. Internally they both call ResourceManager.ProvideResource to load the object. InstantiateAsync will additionally instantiate it.

    2) When a scene is unloaded, there's an internal engine function in SceneManager that calls AddressablesImpl.OnSceneUnloaded. This will then call ResourceManager.CleanupSceneInstances, which releases any game objects created via InstantiateAsync (assuming trackHandle is enabled). Any objects (texture, material, game object, etc.) loaded via LoadAssetAsync will not be automatically released, so you will need to manually call Release on them.

    We've also recently updated our docs and code examples. More info on loading objects can be found in these 2 pages:
     
    Kirsche and KwahuNashoba like this.
  45. khan-amil

    khan-amil

    Joined:
    Mar 29, 2012
    Posts:
    206
    Thanks both for your answers.
    I understand better now, and was mainly confused because I misremembered how it was when instantiating a prefab directly through code using Instantiate (which also looses prefab reference).
     
  46. ttok920623

    ttok920623

    Joined:
    Jun 8, 2022
    Posts:
    1
    Does this mean i have to release addressable assets manually when i load a new scene since InstantiateAsync calls LoadAssetAsync internally anyway and
    you said objects loaded via LoadAssetAsync will not be released automatically.
     
  47. FlightOfOne

    FlightOfOne

    Joined:
    Aug 1, 2014
    Posts:
    668

    I am not entirely sure but you can test and find out by using the event viewer. It will show you if the asset in question is still loaded or not.
    upload_2022-6-9_8-41-33.png

    And make sure to check this:

    upload_2022-6-9_8-43-33.png
     
    ttok920623 likes this.
  48. owen_proto

    owen_proto

    Joined:
    Mar 18, 2018
    Posts:
    120
    I just stumbled upon something I found unexpected:

    I used addressables to instantiate a prefab. I then unparent a child gameobject from the instantiated prefab. When I call Addressables.ReleaseInstance(instantiatedPrefab) it is destroyed as expected and the unparented child object remains. When I call Addressables.ReleaseInstance(unparentedChild) it is not destroyed. When I call Destroy(unparentedChild) it is destroyed. Is Addressables.ReleaseInstanceno longer a blanket replacement for Destroy?
     
    Last edited: Aug 2, 2022
  49. ProtoTerminator

    ProtoTerminator

    Joined:
    Nov 19, 2013
    Posts:
    586
    @owen_proto No, it is not a blanket replacement anymore. They changed it to return a bool if it was released or not. See above comments.
     
    owen_proto likes this.
  50. pillakirsten

    pillakirsten

    Unity Technologies

    Joined:
    May 22, 2019
    Posts:
    346
    No if you used Addressables.InstantiateAsync (with trackHandle=true) to instantiate assets they will be automatically released when the current scene is unloaded. This is extra functionality that InstantiateAsync has, which LoadAssetAsync does not. If you used Addressable.LoadAssetAsync directly to load assets (and maybe you also used Object.Instantiate to instantiate them), then you will need manually release them.