Search Unity

How to load assets synchronously in addressable asset system.

Discussion in 'Addressables' started by Lee-Gyein, Oct 9, 2019.

  1. Lee-Gyein

    Lee-Gyein

    Joined:
    Apr 28, 2016
    Posts:
    1
    Is Unity planing to support for synchronous loading of Addressable Asset?

    We are developing a game and recently we've tried to migrate from old asset bundle system to addressable asset system.

    However Our system was already constructed to load almost resources synchronously and it would be so painful and take a lot of time to change it asynchronous. So we are looking for a way to load resources synchronously with addressable asset.

    First I used 'LoadAssetAsync' function like below codes

    var handler = Addressables.LoadAssetAsync<GameObject>("SomeAddress");
    while (!handler.IsDone);

    Debug.Log("This line will never be called!!");

    But In this case, the property of 'IsDone' never changed. Is it right? If it is just a bug in the latest version of addressables I hope that unity fix it ASAP.

    And I've made some synchronous provider by referencing "SyncAddressables project in https://github.com/Unity-Technologies/Addressables-Sample"
    Unfortunately this wasn't able to cover all cases too. In some cases like loading asset bundle with some dependencies, It didn't work.

    If Unity doesn't have a plan to support for it, Is there any other way to deal this? Is to change sync loading to async loading the only way I can?

    Thanks
     
    Last edited: Oct 9, 2019
  2. StrongCube

    StrongCube

    Joined:
    Nov 22, 2016
    Posts:
    50
    No, addressables is dead asset
     
  3. Zimbres

    Zimbres

    Joined:
    Nov 17, 2014
    Posts:
    180
    Excuse me sir? I'm starting to research on the matter, is Addressables ... dead? Muerto? Expired? Under six feet of dirt? With ants on its mouth?
     
  4. Thermos

    Thermos

    Joined:
    Feb 23, 2015
    Posts:
    148
    He may be just disappointed at the slow or nearly zero response from unity in this forum. Addressable now have many bugs, just see these bug report threads, for me I encountered:

    1. AssetReferenceT<T>.editorAsset is broken if T is subAsset like Sprite.
    2. AddressableWindow and AssetReferenceGUI is extremely slow if you have thousands of assets. Every click takes you 3-5 seconds even when project is saved on SSD.
    3. Addressable build is extremely slow compares to old fashion Resources Or Asset Bundles, it also ignores caches which makes it worse.
    4. All these slow operations are not because of high usage of CPU, because I spent around two weeks to migrate and reordered my entire project, I wrote many automation script like rename all assets in side group, whenever I choose to automatically do something or build the project from scratch, I can play one hour World of Warcraft with high settings and solid 60FPS. I leveled up 2 new characters to lv.120 while waiting for addressable to work.

    it's basically functional, also you can modify the source code if you now how to fix. But still, it's always better to hear more from the dev team, makes people confident.
     
    Last edited: Feb 4, 2020
  5. Zimbres

    Zimbres

    Joined:
    Nov 17, 2014
    Posts:
    180
    Your patience and serenity on reporting so heavy drawbacks is admirable. I.... think that I will try to load/unload stuff using other feature, maybe.
     
    Awarisu likes this.
  6. Thermos

    Thermos

    Joined:
    Feb 23, 2015
    Posts:
    148
    I would suggest using AssetBundle.LoadAsync. if some day addressable become truly production ready, it's easier to migrate.

    As for those thing that must be load synchronously, I can share some of my methods:

    1. You could split your prefab into two or even more parts, one contains minimal scripts, others contains actual assets. When the main part is loaded and gets enabled, it can load assets asynchronously. For example, create a character with basic script, rigidbody and collider and so on, that character is already fully functional even it's invisible for some frames. Then load everything else.

    2. Create a scriptable object called asset linker. It's contains all assets' path that must be ready to use when running games. When game started, load that container first, then wait for loading everything it links, then load your start menu. If you are in play-mode, you could do AssetDataBase.Load(path) instead of AssetBundle.LoadAsync(path) to loading everything synchronously, so all data are ready when you use them.

    3. Make your functions as instructions. For example, if you need to play some particles at some location, instead of create a game object immediately, you create a struct contains (path, position, rotation) and put it into a list. Make a system examining this list every update, see if that particle object is actually loaded and instantiated, if it does, put it at target location and delete this instruction.

    Overall,
    method 1 is most used when dealing with characters, gears, weapons, bullets...You need to do GetComponent() then set some data when they are created. Things gets far more complex if you have to do this asynchronously, especially when dealing with edge cases like you should destroy that character while it's assets are still loading...

    method 2 is most used for loading game database and other assets that lives through the entire game life-time.

    method 3 is most used when dealing with particles, audio clips...These things just need to spawn at some location, and that's all.

    These are just personal experiences, not best practice.
     
    OceanX000 and flamingogs like this.
  7. Jribs

    Jribs

    Joined:
    Jun 10, 2014
    Posts:
    154
    @Zimbres Dont let him scare you away from addressables. There are definitely some cons, but there are also a lot of things that are way better than using traditional AssetBundles.

    For one, using the older system the proper way took a ton of work, Addressables handles a lot of that work for you with out needing anything extra.

    Addressables definitely does have bugs, and it has improved a lot even in the past few months.
     
    EZaca likes this.
  8. Zimbres

    Zimbres

    Joined:
    Nov 17, 2014
    Posts:
    180
    My thing is, I'm planning on how to load content for a simple open-world game, and I'm still on planning phase. I must say... I'm scared to adopt something from Unity if there's no certainty. Unity's history tells that it's better to work with fully developed features and dont take anything as granted. It reminds me on how much time it's new input system is being developed, how much time nested prefabs took to happen, etc.

    I dont know I'm crazy or not, but I'm thinking on just use some system for loading and unloading scenes async. It have it's problems... but I'm still researching it.
     
  9. ProtoTerminator

    ProtoTerminator

    Joined:
    Nov 19, 2013
    Posts:
    586
    If you're scared to use addressables because it's still getting patches, just implement your system with assetbundles. Then when you feel addressables is stable enough for you, it's relatively easy to convert.
     
  10. rastlin

    rastlin

    Joined:
    Jun 5, 2017
    Posts:
    127
    @Topic - Just use async & await, and you have a synchronous loading. In my project all assets are preloaded before the game starts which is almost identical to synchronous loading.

    @Addressables - People reporting problems here witch addressable probably has a very little experience with the package. There are definitely a lot of cons, but the number of benefits greatly outweighs those. I have 6GB in total of asset bundles and manually managing those with old workflow is not feasible.

    Ultimately, if there is some problematic issues with the asset itself, you could fix or rewrite it yourself, you have a full source code.
     
  11. LeleUnity

    LeleUnity

    Joined:
    Jul 30, 2016
    Posts:
    97
    Could you show how to return a GameObject Value syncronsly from Addressables?
    I need to wait the object to be fully loaded before to continue the game
     
  12. LeleUnity

    LeleUnity

    Joined:
    Jul 30, 2016
    Posts:
    97
    Hello,
    I am struggling with events in Addressables. Because of the lack of a simple syncronized load method.
    ----------
    **What happens if I override the variable textureHandle before it triggered?**
    The previous delegate is deleted and not notified anymore, or It will trigger twice?
    are they considered two different events?
    ----------
    Code (CSharp):
    1.      AsyncOperationHandle<GameObject> textureHandle = Addressables.LoadAssetAsync<GameObject>("AssetAddress");
    2.         textureHandle.Completed += ElementToNotify1.TextureHandle_Completed;
    3.  
    4.         AsyncOperationHandle<GameObject> textureHandle = Addressables.LoadAssetAsync<GameObject>("AssetAddress");
    5.         textureHandle.Completed += ElementToNotify2.TextureHandle_Completed;
    ----------
    P.S. This code is in a class named DataManager.
    I have a class Dog and a class Cat, I need both to spawn a poo gameobject, with addressable.

    I would like to write in Dog and Cat classes a method LoadPooAsync() that will call the DataManager and pass to them their object reference so, when the object is loaded it will trigger the event for the right object who asked for it.
    I tried to write something with Actions but didn't work..
    Could you help me to write the methods signatures?
     
  13. HedgehogNSK

    HedgehogNSK

    Joined:
    Jun 3, 2017
    Posts:
    24
    Compilier must tell you that you can't define second variable because you already have variable with the same name. If you mean not to define but to assign new value, it won't delete the current async operation but you just can't get to it anymore. So It will be executed anyway. You should read about garbage collector in Csharp, it will helps you a lot in this question.

    If you want to subscribe 2 different methods to 1 event you don't need to load assets twice.

    Code (CSharp):
    1.  
    2. AsyncOperationHandle<GameObject> textureHandle =
    3.                     Addressables.LoadAssetAsync<GameObject>("AssetAddress");
    4. textureHandle.Completed += ElementToNotify1.TextureHandle_Completed;
    5. textureHandle.Completed += ElementToNotify2.TextureHandle_Completed;
     
    Last edited: May 12, 2020
  14. LeleUnity

    LeleUnity

    Joined:
    Jul 30, 2016
    Posts:
    97
    No, Read carefully.
    I want each element to subscribe to a different event.
    My question is:
    If I ovverride the variable textureHandle with another call
    Code (CSharp):
    1. AsyncOperationHandle<GameObject> textureHandle =
    2.                     Addressables.LoadAssetAsync<GameObject>("AssetAddress");
    BEFORE the old trigger is fired
    Code (CSharp):
    1. textureHandle.Completed += ElementToNotify1.TextureHandle_Completed;
    What will happen?
    It will fire both methods when event1 happens? or it will forget the previous subscribtion since I have overriden that variable?

    Read carefully my previous message.
     
  15. ProtoTerminator

    ProtoTerminator

    Joined:
    Nov 19, 2013
    Posts:
    586
    @LeleUnity The handle passed to Completed is the same handle that Completed is called on. So, despite you overwriting the handle variable, the correct one will still be passed to the completed callback.


    Code (CSharp):
    1. AsyncOperationHandle<GameObject> handle;
    2.  
    3. handle = Addressables.LoadAssetAsync<GameObject>("address1"); // handle1
    4. handle.Completed += handle1 => ElementToNotify1.HandleCompleted(handle1);
    5.  
    6. handle = Addressables.LoadAssetAsync<GameObject>("address2"); // handle2
    7. handle.Completed += handle2 => ElementToNotify2.HandleCompleted(handle2);
    [EDIT] To answer your other question, it will fire both callbacks independently when each operation has completed.
     
  16. LeleUnity

    LeleUnity

    Joined:
    Jul 30, 2016
    Posts:
    97
    Are you sure? This may not happen if the variable is overriden BEFORE the callback of handle1 is fired!
     
  17. ProtoTerminator

    ProtoTerminator

    Joined:
    Nov 19, 2013
    Posts:
    586
    It doesn't matter. As long as you subscribe to the event before you overwrite the variable, it will work as I described.
     
  18. LeleUnity

    LeleUnity

    Joined:
    Jul 30, 2016
    Posts:
    97
    how can a ScriptableObject be loaded with addressables?
     
  19. grofie

    grofie

    Joined:
    Dec 9, 2013
    Posts:
    30
    You can use WaitForCompletion to synchronously complete the async operation:

    Code (CSharp):
    1. AsyncOperationHandle<T> resourceRequest = Addressables.LoadAssetAsync<T>(FileName);
    2. _instance = resourceRequest.WaitForCompletion();
    3.  
     
  20. N8W1nD

    N8W1nD

    Joined:
    Sep 3, 2020
    Posts:
    9
    Nice Stuff, thank you !! <3