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. Dismiss Notice

Why are there no synchronously LoadAsset APIs?

Discussion in 'Addressables' started by zhuxianzhi, Jul 11, 2018.

  1. TextusGames

    TextusGames

    Joined:
    Dec 8, 2016
    Posts:
    426
    upload_2019-10-24_13-15-4.png

    Bill said that "they are exploring synchronous interfaces". (

    I sincerely hope they will decide to officially include synchronous API into the Addressable package.:rolleyes:
     
    Last edited: Oct 24, 2019
    Peter77 likes this.
  2. zhuxianzhi

    zhuxianzhi

    Joined:
    Mar 30, 2015
    Posts:
    120
    There are a lot of problems with the synchronous loading example. The core problem is that when using remote groups, the caching mechanism relies on UnityWebRequest to implement. (When resources are already cached in the local directory, they still need to be loaded asynchronously using UnityWebRequest.)
     
    5argon likes this.
  3. nilsdr

    nilsdr

    Joined:
    Oct 24, 2017
    Posts:
    374
    Is there an example of an implementation of this?
     
  4. hadmaerd

    hadmaerd

    Joined:
    Sep 6, 2014
    Posts:
    13
    What about Dependency Injection plugins? Such as Zenject, Adic and others, they all rely on synchronous workflow as far as I know, and they can't bind to any assets which can't be reached immediately, so the only way there is still using Resources. Ofcourse people do write their own asynchronous DI solutions, and those are better than synchronous ones in many ways, but it still looks like a good example of synchronous loading usecase.
     
  5. almosr

    almosr

    Joined:
    Jul 16, 2017
    Posts:
    14
    So, is relying on the value from
    Code (CSharp):
    1. AsyncOperationHandle.IsDone
    property right away after calling the
    Code (CSharp):
    1. Addressables.LoadAssetAsync<T>()
    too hacky? Just like how it is done here:
    https://github.com/Unity-Technologies/Addressables-Sample/blob/master/Advanced/Sync Addressables/Assets/SyncAddressables/SyncAddressables.cs#L34

    I understand that it makes use of a potential side-effect/implementation detail, but for the time being this looks like an acceptable workaround to me.
     
    tudor_unity816 likes this.
  6. Neto_Kokku

    Neto_Kokku

    Joined:
    Feb 15, 2018
    Posts:
    1,751
    Asset Bundles support sync loading. You can even turn an async load operation into a sync one by trying to access the bundle property of an AssetBundle request: the thread will stall until loading is finished.

    Addressables is an asset bundle manager with download and cache management capabilities, and deep editor integration (which marketing is selling as an asset bundles replacement, confusing lots of people) . Therefore, there's nothing preventing the addition of sync APIs to Addressables on a technical level, it's just a matter of the AAS team figuring out an elegant way to implement it.

    Just make the thing throw an exception if people try to call the sync APIs on remote groups or something.
     
    chanon81 likes this.
  7. zhuxianzhi

    zhuxianzhi

    Joined:
    Mar 30, 2015
    Posts:
    120
    Asset Bundles' API does support synchronous loading, but overall the design of Addressables has caused a lot of flaws, even if you modify the source code.
    1. Even if the remote resource is cached locally, the resource needs to be accessed asynchronously. (Requires custom cache mechanism)
    2. Synchronous group cannot support asynchronous loading and synchronous loading at the same time.
    3. Release issues after synchronous loading. The TrackHandle callback mechanism is not synchronous.
     
    chanon81 likes this.
  8. davidrochin

    davidrochin

    Joined:
    Dec 17, 2015
    Posts:
    72
    +1 for synchronous loading. I need it to implement the IPunPrefabPool interface from Photon Pun.

    I think synchronous loading should be supported because a lot of us depend on third-party tools that need this kind of loading. It's great that you want to encourage Unity developers to do stuff in the right way (async), but I don't think anything should be enforced.

    Not to mention that Unity is used for prototyping a lot, and in those cases devs NEED to do things the fast way and not the right way, and that is perfectly valid in prototyping.

    Right now we are in the need of finishing this multiplayer prototype, and your design decision is making things 100x harder for us.
     
    Last edited: Mar 7, 2020
  9. magmagma

    magmagma

    Joined:
    Oct 27, 2017
    Posts:
    41
    We are using the I2 localization plugin for our game. Integrating addressables was a real big pain in the butt because I2 is made to work with asset bundles and handles everything synchronously.

    Basically I had to modify a toooooon of code from I2 to make it work. It is working now, but I wish I hadn't needed to spend so much time on that (´゚д゚`)

    A synchronous version of loading functions in addressables would have helped immensely. And it will probably still help a lot of people in similar situations.
     
    chanon81 and davidrochin like this.
  10. Daerst

    Daerst

    Joined:
    Jun 16, 2016
    Posts:
    275
    I too would appreciate this feature, e.g. I'd like to load Localization data as first thing when the application loads (even before the scene is loaded) using RuntimeInitializeOnLoadMethod and it should just block until localization data is there.
     
    chanon81 likes this.
  11. chanon81

    chanon81

    Joined:
    Oct 6, 2015
    Posts:
    168
    People have been begging for this since 2018 or practically the beginning of Addressables.

    Addressable's team seems to want to prescribe to everyone that async everything is the 'superior' way.

    But as many here say, synchronous API would make people's lives so much easier and since Addressables is managing one of the most basic things which is loading assets the fact that it requires async forces everything above it (ie. all of your game code) to inherit this needless complexity.

    A well designed API should make sure that the most common and simple usage case is easy to use and has the least impact upon the code that uses it. Here instead Addressable team's dogmatic requirement for async APIs means even the simplest usage of Addressables requires that any game that decides to use it must do painful architectural overhaul to support async.

    I really don't understand this design decision and their stubborness in sticking with it.

    Developer (our) usage experience should have higher priority than dogmatic design decisions.


    One of the most common use cases is like this comment says:

    Why not just supply a method to download required dependencies - actually I think there is one already. But also provide a synchronous LoadAsset which just returns null if the asset isn't available in any locally cached asset bundles. Maybe a synchronous bool AddressableExists(string key), and bool AreAllDependenciesDownloadedFor(string key) too.

    Just provide a sync api where the developer can manage things themselves instead of hiding all of it and then forcing async everything.

    Actually, the simplest and most common use case is just loading an asset from a local asset bundle (one that is included with the game). There is really no reason why that must be an async operation, yet Addressable designers require us to use async for it.

    Anyways, I've already built a framework to manage all this asyncness in my game (ie. a cache layer that can synchronously return cached assets), so at this point I'm ok with it. But it is just more work that everyone who begins to use Addressables will have to do .. instead of Addressables providing it for them.

    Collectively, Unity game developers will potentially waste man-years because of this.

    I am saying this after completion of integrating Addressables to my game, so I know how much time it can take and how much pain it can be.

    See this post, for an example of the pains/issue it causes.
     
    Last edited: Apr 9, 2020
  12. chanon81

    chanon81

    Joined:
    Oct 6, 2015
    Posts:
    168
    Here is what the API for sync usage might look like:

    Code (CSharp):
    1.  
    2. // in UnityEngine.AddressableAssets.Addressables
    3.  
    4. // returns null (or maybe throw exception) if addressable not available in any locally cached asset bundles
    5. public static TObject LoadAssetSync<TObject>(object key);
    6.  
    7. // returns null (or maybe throw exception) if addressable not available in any locally cached asset bundles
    8. public static GameObject InstantiateSync(object key, Transform parent = null, bool instantiateInWorldSpace = false, bool trackHandle = true)
    9.  
    10. // used to check if specified key exists
    11. public static bool AddressableExistsSync(object key);
    12.  
    13. // used to check to make sure everything needed is downloaded
    14. public static bool AllDependenciesDownloadedForSync(object key);
    15.  
    16. ////////////////////
    17.  
    18. // these are the existing Async API, would be used to download any required dependencies
    19. public static AsyncOperationHandle DownloadDependenciesAsync(IList<object> keys, Addressables.MergeMode mode, bool autoReleaseHandle = false)
    20. public static AsyncOperationHandle DownloadDependenciesAsync(object key, bool autoReleaseHandle = false)
    21.  
    22.  
    With above set of APIs, we can use the DownloadDependenciesAsync methods to download the required dependencies before starting a level. Then the code inside the level can use LoadAssetSync and InstantiateSync to load any assets or instantiate prefabs.

    Any 'local' AssetBundles that are included with the game can be immediately used with LoadAssetSync without having to worry about downloading them or managing async.

    All of the Sync methods require that Addressables has been initialized. Actually a synchronous Addressables.InitializeSync would be good too.
     
    Last edited: Apr 2, 2020
  13. chanon81

    chanon81

    Joined:
    Oct 6, 2015
    Posts:
    168
    A further idea and possibly even simpler way is to just provide an API call to ensure the specified addressable group's asset bundle(s) is downloaded. Then afterwards all LoadAssetSync calls for assets inside that addressable group would succeed.

    So, added to above:

    Code (CSharp):
    1.  
    2. // in UnityEngine.AddressableAssets.Addressables
    3.  
    4. // ensures all asset bundles for the specified addressable group has been downloaded
    5. // afterwards all LoadAssetSync calls to any assets in the addressable group would succeed.
    6. public static AsyncOperationHandle EnsureAddressableGroupDownloaded(string addressableGroupId, bool autoReleaseHandle = false)
    7.  
     
  14. Daerst

    Daerst

    Joined:
    Jun 16, 2016
    Posts:
    275
  15. chrisk

    chrisk

    Joined:
    Jan 23, 2009
    Posts:
    704
    no replies from Unity employees for more than a year. "We are listening... blah blah...", yeah.. just listening...
     
  16. ProtoTerminator

    ProtoTerminator

    Joined:
    Nov 19, 2013
    Posts:
    566
    Well, a year ago they said there were no plans to implement a synchronous load API. And they just recently said there will be no new feature work for a while so they can iron out bugs and stability issues.

    So I wouldn't get my hopes up for a sync API any time soon (or ever).
     
    TextusGames likes this.
  17. chanon81

    chanon81

    Joined:
    Oct 6, 2015
    Posts:
    168
    Yes, I was thinking the same too which is a big shame as some people (as already evident in this thread) will not be able to use Addressables.

    But if people continue to express the desire/need, maybe they will consider adding it after they finish the stability work.

    It is good though that they focus on stability and bugs now cause Addressables really needs that too.
     
  18. lejean

    lejean

    Joined:
    Jul 4, 2013
    Posts:
    383
    I want to implement addressables in my game to improve scene load times but now that I tried it I don't really understand what it's best used for except for loading a big scene or something.

    It doesn't seem to be good for creating stuff at runtime.

    This is my current use case:
    - Scene loads
    - Push start to play -> player prefab addressable InstantiateAsync

    The problem:
    - It spawns after a second or so instead of instantly
    - Pushing start multiple times spawns multiple player objects because it's async instead of instant.

    So now I need to add a boolean check to prevent the spawn code from running again while the operation isn't finished.

    So because of this I see future problems coming up, like instantiating a particle for a player attack or something.
    If I push the button it needs to be instant obviously not spawn after a second.

    So what am I supposed to do?
    Is this not what addressables is meant for?
     
  19. MaskedMouse

    MaskedMouse

    Joined:
    Jul 8, 2014
    Posts:
    1,058
    Addressables are for dynamic loading assets where it doesn't matter whether it comes from the server or from streaming assets. You use the same code to load the same asset.

    If you require the asset to be nearly instantaneously you can preload them, moving the load times somewhere else. Because at some point you got to load the asset, it has to be done in order to be used.

    Addressable assets don't necessarily decrease your Scene Loads. For a player asset if you need it instantly and that asset doesn't get updated frequently, I'd just embed it into the scene instead of making it an addressable asset. If it does frequently get updated, preload it so you don't have to wait long before instantiating.

    There will always be load times, addressable assets doesn't take that magically away. What addressable assets does is provide a way to dynamically load assets into memory so that you don't have to load the full scene in order to start.
    But you have to account for this dynamic loading by either preloading the assets or somehow hide the fact that you're loading them (so many ways around this).

    In your setup you might want to disable listening for "Start" after the operation has been initiated. It's not that much of a huge change. I don't know your specific case but you can also go the other way around about it.
    First load the player prefab and once that is finished show the Start button.
    It all depends on when you need it, does it update frequently and whether you need it instantly.
    In most cases when the asset is already downloaded it loads the asset in a few frames because it comes from disk instead of network. I'd say that should be fast enough.

    I mark my addressables that I need instantly but are frequently updated with Essential tag. When I load the application I pre-load all assets with that tag. Then Instantiate them when I need them.
     
    phobos2077, ProtoTerminator and Baste like this.
  20. WaaghMan

    WaaghMan

    Joined:
    Jan 27, 2014
    Posts:
    241
    I guess people that understood and wanted sync addressables will need to go their own way. We have, by building an entirely separate system from the Addressables package. We still use the editor UI for asset and group management, but we build the assetbundles ourselves and load them at runtime by using the AssetBundle API.

    In short, all we do is generate a file having all asset addresses and GUIDs referenced to the asset path in the bundle, and load them into a dictionary on startup.

    We offer the same signature for methods and use the same API the Addressables system uses internally (also with less overhead due to complex async constructs), but we also provide methods to use the Synchronous part of the API. It wasn't that hard, and we're now happy to have the best of both worlds.
     
    Shawn-Halwes, lclemens and chanon81 like this.
  21. cmbliu

    cmbliu

    Joined:
    Jun 4, 2017
    Posts:
    14
    Honestly, people don't waste your time.

    I had searched the internet UP SIDE DOWN for 2 weeks, and I don't see any real time example that uses addressable assets (All I had found are useless examples that load somethings and wait for the loaded asset to show up with a delay). For example, if my character needs to equip a weapon, the weapon model must be loaded immediately. If I use addressable asset, my game crashes, because my gameObject variable is null, since the addressable system takes time to load.

    Some people say that I need to pre-load them. When? When do I do that? How the hell I know which weapons the player wants to equip? So you are telling me to pre-load all weapon models the player owns? If so, using addressable system is TOTALLY useless, since it will not save you much memory because you have to pre-load all the weapon models anyway (if the player owns all the weapons in the game). In the end, I better off using direct reference, because my code will be simpler without all the pre-load logic (not to mention the logic to release the addressable assets).

    In my opinion, the addressable assets system is just a waste of my time (I spent 2 weeks researching about it, and get nothing out of it)
     
  22. MaskedMouse

    MaskedMouse

    Joined:
    Jul 8, 2014
    Posts:
    1,058
    @cmbliu Addressable Assets are nice to update the assets via a server. If you want to change your weapons model or update it. You have to rebuild the entire game which is a waste of time.
    So if you require to have everything available you can indeed simply pre-load the assets so that they're cached to disk.
    When? Well everytime you open the game or if you have a login screen simply check whether the game has an updated catalog. If so, download all the updated assets. Instead of recompiling the game, uploading it so that people can redownload the game again. Which may only include 1 small updated asset whereas the game is 300 mb or maybe in the gb's.
    As for memory, it completely depends on how you handle the loading. If everything is on disk and loaded via addressables when you need them. You're only loading in the assets that you require to load.

    There are pro's and con's about addressables and you have to plan ahead.
    If you only have a small game, small assets that do not change, addressables may not be feasible.
    But for a large(r) game with many assets where a lot of them do change. Addressables is a nice way to update.
    So again, it completely depends on your use case whether addressables is something you'd need.

    I don't find addressables complex per sé. It depends on how complex you're making it for yourself.
     
  23. LuGus-Jan

    LuGus-Jan

    Joined:
    Oct 3, 2016
    Posts:
    169
    @cmbliu I think you might be missing the point of Addressables then. It is a content/asset management system, but you have to keep in mind the way it works for it to be properly integrating it in your game. You have to build your game around it. When people say that your best workaround would be to pre-load obviously depends on your situation of how you deal with your game data. The easiest solution would to pre-load it in a scene before you actual game starts (i.e. in the splash screen or something, which would naturally not be very memory efficient), or as you describe in your example, when the player opens up his inventory to maybe equip a sword, start loading in the assets of the items in that inventory, and clear the loaded assets when he closes it. There are still some edge cases to be found here and there, but the overall gist of it could be something like that.

    I do think it is generally best practice to make your asset loading asynchronous, as it tends to spread out heavy loading operations and reduce frame stutter whenever you need an asset (although I do think they can improve in that regard, but that's more an engine problem I feel, and not an issue of Addressables itself), and gives you better control of which assets are loaded in memory.

    I spent nearly 6 months adapting our game to use Addressables instead of just plain Asset Bundles and Resources. We ran into a limit of Resources (where it can't contain more than 4GB of asset data), and Asset Bundles was a pain to work with in editor (each time a level was modified, it needs to rebuild the bundle). Addressables addresses (haha!) both these issues, but since it imposes another limitation, namely the way you load content, you need to take that up into your codebase.

    It's unfortunately not a drop in/out system that outright replaces other systems with the click of a button, but definitely a step in the right direction as how games should generally deal with content. It still has its flaws (I do have developed a love/hate relationship with it over time), but it's a package I would definitely use again in any new project I start. (I do hope they make it less complex on the code-side of things if they ever decide to go for a V2).
     
  24. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,001
    No he is not. Addressables is being touted as a replacement for the Resources folder. His use case is something that the Resources folder fits quite well, but all communication from Unity says don't use Resources, use Addresssables instead.

    Having to build your game around a certain feature, when what you really want from that feature is "IF X LOAD MODEL A ELSE LOAD MODEL B" is kind of insane.
     
  25. jRocket

    jRocket

    Joined:
    Jul 12, 2012
    Posts:
    687
    I don't get it. Judging from the amount of posts about it on these forums, a synchronous API is probably the most requested feature for Addressables. So, why is Unity not listening to their customers?
     
  26. joe_nk

    joe_nk

    Joined:
    Jan 6, 2017
    Posts:
    67
    I've converted a large project to using Addressables. We're able to use the SyncAddressables stuff provided by Unity to load things in-game where our code is already too complicated/relies on synchronous loading to refactor right now (Though refactoring to async loads is still on our roadmap). We're able to do this because our game (a mobile game) has a phase on startup where it downloads and caches any missing content. That means that our asset bundles are guaranteed to at least be available on disk, so we can load things in a synchronous way using SyncAddressables (The group is configured to use an asynchronous asset bundle provider, so we can download, but a synchronous asset provider)

    I'd suggest that this model is easiest to transition to when converting an existing project. Downloading everything upfront is pretty user friendly, especially for those using mobile data) so being able to guarantee a load wouldn't result in a download is very handy.
     
    Last edited: Sep 14, 2020
  27. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,001
    They were too focused buying up other companies and launching half baked and expensive services left and right because diversifying revenue sources looks good for IPO purposes.
     
    Freznosis likes this.
  28. zhuxianzhi

    zhuxianzhi

    Joined:
    Mar 30, 2015
    Posts:
    120

    In a group, you can only load either synchronously. Either asynchronous. And if the synchronous group depends on the resources of an asynchronous group, there will be problems.
    This sounds terrible, this was originally a function supported by AssetBundle (supporting both synchronous and asynchronous, it has been ensured that this AssetBundle is local)
     
  29. joe_nk

    joe_nk

    Joined:
    Jan 6, 2017
    Posts:
    67
    Yes, there is that caveat. We have one 'sync' bundle and we're also able to guarantee that it has no dependencies on other bundles.
     
  30. Elringus

    Elringus

    Joined:
    Oct 3, 2012
    Posts:
    482
    Why not make addressables API thread-safe? This will solve all the issues: no need to add sync APIs and we'll be able to hang the main thread and use the async APIs on a background one.

    Not providing sync APIs and at the same time limiting the system to run on the main thread is just rude, no matter the case.
     
  31. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,194
    @unity_bill, what happened to the exploration of the synchronous interface?

    We needed a system for loading assets through a name/address rather than referencing them directly, and the async requirement of Addressables was such a pain in the ass to work around that I simply fell back to Resources. I fought against the Addressables async requirement for a whole work day to try to get it working, the Resources solution didn't require me to do anything else than spell out the code.

    Here's a longer version of the actual use-case we were running into:
    I have some assets that are needed on startup by a bunch of other systems. These assets are essentially scene metadata, and contains things like light settings, camera boundaries and settings, spawn points, etc. So these assets needs to be ready on demand for the camera, light, player, or anything else can be spawned and set up.

    The old way we handled these was to have a "database" asset that simply kept a list of all of the assets. The database asset was loaded by being in Preloaded Assets, and loading itself in builds, and through the AssetDatabase in the editor. Rough outline:

    Code (csharp):
    1. public class SceneMetadataDatabase : ScriptableObject {
    2.     [SerializeField]
    3.     private List<SceneMetaData> sceneMetaData;
    4.     public static IReadOnlyList<SceneMetaData> SceneMetaData => Instance.sceneMetaData;
    5.  
    6.     private static SceneMetadataDatabase _instance;
    7.     private static SceneMetadataDatabase Instance {
    8.         get {
    9. #if UNITY_EDITOR
    10.             if (_instance == null)
    11.                 _instance = AssetDatabase.LoadAssetAtPath<SceneMetadataDatabase>("...");
    12. #endif
    13.             return _instance;
    14.         }
    15.     }
    16. #if !UNITY_EDITOR
    17.     void OnEnable() {
    18.         _instance = this; // happens immediately when a build boots.
    19.     }
    20. #endif
    21. }

    There's some problems with this solution, though.
    - Stuff in preloaded assets means that loading the first screen in the game takes longer
    - The database asset didn't do anything useful, and was getting merge conflicts when two people made new scenes at the same time.

    To solve the above, we wanted to ditch the database asset entirely, and instead just load all of the assets on-demand. There's essentially two ways to load assets that are not referenced (indirectly) from a scene or preloaded assets in Unity:
    - through AssetBundles
    - through Resources

    Resources has gotten a big "don't use this" flag, and there's some downsides with the API, and since Addressables is the big new solution to all "load by address" problems, we wanted to go with it.

    So, the goal here is to turn SceneMetadataDatabase into a static class, and load the data through Addressables. Setting up the solution asset-wise was pretty pain-free; mark all of the SceneMetaData files as Addressable, and give them a tag so they could be loaded in bulk.

    So my solution became:

    Code (csharp):
    1. public static class SceneMetadataDatabase {
    2.     private static Task loadOp;
    3.     private static bool loaded;
    4.  
    5.     private static List<SceneMetaData> sceneMetaData;
    6.  
    7.     public static async Task<IReadOnlyList<SceneMetaData>> GetSceneMetaData() {
    8.         if (!loaded) {
    9.             if (loadOp == null) {
    10.                 sceneMetaData = new List<SceneMetaData>();
    11.                 loadOp = Addressables.LoadAssetsAsync<SceneMetaData>("SceneMetaData", obj => { sceneMetaData.Add(obj); }).Task;
    12.             }
    13.             await loadOp;
    14.             loaded = true;
    15.         }
    16.         return sceneMetaData;
    17.     }
    18. }

    I'm a bit shaky on if it's the right way to do things (and it's code straight from memory), but the essence is that the code isn't very bad here, but instead of providing a list of SceneMetaData, the class now provides an awaitable Task that will eventually return the list.

    And boy oh boy is that a problem!

    Everything that used to do this:

    Code (csharp):
    1. private SomeData someData;
    2.  
    3. void Start() {
    4.     var metadata = SceneMetadataDatabase.SceneMetaData;
    5.     someData = GetDataFrom(metadata);
    6. }
    7.  
    8. void Update() {
    9.     DoSomething(someData);
    10. }
    11.  
    now has to do this:

    Code (csharp):
    1. private SomeData someData;
    2. private bool dataLoaded;
    3.  
    4. async void Start() {
    5.     var metadata = await SceneMetadataDatabase.GetSceneMetaData();
    6.     someData = GetDataFrom(metadata);
    7.     dataLoaded = true;
    8. }
    9.  
    10. void Update() {
    11.     if (!dataLoaded)
    12.         return;
    13.     DoSomething(someData);
    14. }
    And that's annoying, but guess what? Scripts are not independent! Some other script might want to pull data from the above script. Now the above script needs to make it's methods async, and this propagates pretty much to the entire game!

    I also pretty much have to throw up a black screen at start and wait for all of that loading anyway, because the player, camera, light, everything can't spawn yet because there's no data. So instead of waiting a couple of milliseconds for the files to load, I wait at least a whole frame of black screen - or more, since the Addressables system has to boot.

    And why exactly am I doing all of this work? Because I want to load a file that I'm 100% sure could be loaded near-instantly with a File.Load operation - it's in an AssetBundle, right next to the installation.

    So I scratched my head, and tried to think of a better solution. It was pretty obvious:

    Code (csharp):
    1. public static class SceneMetadataDatabase {
    2.     private static SceneMetaData[] sceneMetadata;
    3.     public static IReadOnlyList<SceneMetaData> SceneMetadata {
    4.         get {
    5.             if (sceneMetadata == null)
    6.                 sceneMetadata = Resources.LoadAll<SceneMetaData>("SceneMetaData");
    7.             return sceneMetadata;
    8.         }
    9.     }
    10. }
    Now I don't have to bleed a single asynchronous call out to a bunch of code, and everything just works.

    In short, we had a small problem. We tried to introduce Addressables, and we got a huge problem instead. Going over to Resources not only removed the problem, but also shortened our code substantially and killed off any edit time/runtime code path differences.

    But the code I wanted to write was this:

    Code (csharp):
    1. public static class SceneMetadataDatabase {
    2.     private static SceneMetaData[] sceneMetadata;
    3.     public static IReadOnlyList<SceneMetaData> SceneMetadata {
    4.         get {
    5.             if (sceneMetadata == null)
    6.                 sceneMetadata = Addressables.LoadAssetsSync<SceneMetaData>("SceneMetaData");
    7.             return sceneMetadata;
    8.         }
    9.     }
    10. }
    That'd allow us to load the assets from asset bundles in a comfortable way, without taking on the enormous cost of an asynchronous operation we didn't need, that made our game and our code worse.


    It cannot be hard to make a synchronous version of the API. All the arguments for not making it absolutely reeks of "we at Unity know better than our users how our users should write their games". We understand that we will have to change our sync code to async if we move our assets to a CDN, we're not idiots.

    It's baffling to me, absolutely, insanely baffling, that you've managed to make an entire asset management system, but can't wrap a damned blocking call. It's essentially taking all the hard work you did at making Addressables, and just skipping the last 5% of work that'd make it useful.


    The SyncAddressables example from the repo is just silly, as it's essentially just my "return if not ready yet" code from above written in a bloated way, so it's not synchronous at all, and not a solution to a real problem anyone had.
     
    mvaz_p, dacarrera, chanon81 and 8 others like this.
  32. Elringus

    Elringus

    Joined:
    Oct 3, 2012
    Posts:
    482
    I really hope Addressables will get sync APIs and become a default package, while the old Resources system with all its magical folders mess will be removed eventually.
     
  33. brunocoimbra

    brunocoimbra

    Joined:
    Sep 2, 2015
    Posts:
    677
    Endahs, Elringus and RunninglVlan like this.
  34. Endahs

    Endahs

    Joined:
    Sep 16, 2014
    Posts:
    94
    We eventually wrote a whole custom sync API over top of the Addressables async API, but I agree with @Baste and @Elringus: it would have been nice to have a proper Addressables sync API to use out of the box. Async is nice but it comes with a lot more complexity than sync, and in some cases you NEED sync for some 2D visual effects.

    Unity did eventually add sync examples in their Addressables documentation, you may need to check the latest versions of it to see it.
     
  35. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,001
    Kirsche likes this.
  36. Neto_Kokku

    Neto_Kokku

    Joined:
    Feb 15, 2018
    Posts:
    1,751
    What's worse is that Asset Bundles, the thing Addressables is actually using behind the scenes to store and load assets, does support sync loading. Heck, you can even turn an async operation into a sync one on the fly.
     
    chanon81 and TextusGames like this.
  37. Endahs

    Endahs

    Joined:
    Sep 16, 2014
    Posts:
    94
    Interesting fact: this is one of the most popular threads on the Addressables sub-forum. The other super popular thread is the one with the title "Why is Addressables so complicated".
     
  38. pitchblende

    pitchblende

    Joined:
    Jan 9, 2020
    Posts:
    71
    So I came here looking for a good replacement for the Resources folder, since the Unity docs told me that Resources folders are deprecated (or at least their tutorial is) and to look at Addressables instead. So I've just spent a lot of time trying to understand how to simply load an asset that isn't referenced by my active scene, but from this thread it sounds difficult.

    I understand how to make an asset "addressable", but I've run into a brick wall with the async API. Can someone give me a hint how to convert the asynchronous load into a synchronous one please?
     
  39. Endahs

    Endahs

    Joined:
    Sep 16, 2014
    Posts:
    94
    Unity added examples to their Addressables documentation to show some synchronous ways to call their asynchronous methods. The documentation is still a bit weak, but see: https://docs.unity3d.com/Packages/c...al/AddressableAssetsAsyncOperationHandle.html

    Note that if you are embarking on an async journey that there is overhead involved in both code and complexity. When you request async assets you may need to track the in-progress and completed loads, so that you can release them later, or manage situations where mutliple GameObjects in your project request the same assets. Addressables is a powerful system, but there is a lot of initial code overhead and architecture that may be required that isn't really covered in their documentation.

    Unless you are taking advantage of some of the best Addressables features, like having your assets bundled and available local or over the internet, updating bundles instead of the entire APK for mobile, etc, you may want to stick with Resources.Load. Especially so if your project is only ever going to access local resources (not over the internet). I would guess that the vast majority (95% ?) of Unity projects today are still using the simple one-line Resources.Load and developing and releasing faster because of it.

    Good luck :)
     
    Last edited: Jan 3, 2021
    twhittaker likes this.
  40. cwennchen

    cwennchen

    Joined:
    Nov 22, 2019
    Posts:
    7
    we need sync api, please
     
  41. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    5,994
    2 years later, can they now?
     
  42. davidla_unity

    davidla_unity

    Unity Technologies

    Joined:
    Nov 17, 2016
    Posts:
    736
    We're actually working on it right now. It'll be released in a preview version of the package first. But we're looking to have it sometime this month. Not the next release (in a couple days), but likely the release after that or so.

    Can't make any concrete deadline promises. Just know it's coming.
     
  43. yusufdemir2012

    yusufdemir2012

    Joined:
    Dec 21, 2013
    Posts:
    49
    Hi. Do you have any news?
     
  44. davidla_unity

    davidla_unity

    Unity Technologies

    Joined:
    Nov 17, 2016
    Posts:
    736
  45. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,001
    Huh.
     
    akasabutski and Endahs like this.
  46. davidla_unity

    davidla_unity

    Unity Technologies

    Joined:
    Nov 17, 2016
    Posts:
    736
    @AcidArrow so, yeah, this is actually due to a bug in the engine side of things. It's been fixed but isn't in a released version just yet. There's also someone working to backport the fixes. After the fix to the engine the sync APIs were actually quite a bit faster than the async APIs (and should put them more on par with traditional loading APIs). But, for now, the warning is a valid one.
     
  47. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,001
    Cool. Maybe mention parts of that in the docs? (maybe not the full explanation but maybe at least imply that this is a temporary thing and not something inherent to the way the feature is architected (which is what I assumed)).

    I'm just saying all this because reading that line in the docs made me go "Oh, ok, I guess I'm never touching addressables" and it would be a shame if that solidified because I didn't get correct / full information.
     
  48. davidla_unity

    davidla_unity

    Unity Technologies

    Joined:
    Nov 17, 2016
    Posts:
    736
    Good point, I'll make a note on our end to add something to the docs.
     
  49. laurentlavigne

    laurentlavigne

    Joined:
    Aug 16, 2012
    Posts:
    5,994
    oh I like this very much!
    upload_2021-3-11_21-39-29.png
    I was just wondering how I'll manage load time on the Switch. When you say it's go, I'll give this a shot.
     
    Elringus likes this.
  50. ritro_hype

    ritro_hype

    Joined:
    Aug 31, 2020
    Posts:
    5
    Sorry, but that does not seem to work. We use addressables in our project with Quantum and had a race condition issue which will freeze entire game sometimes on some devices (not all of them) upon loading some resources (also not all of them) and this WaitForCompletion looks to me more like a sugar around waiting IsDone on handler, while the thread blocking happens in LoadAssetAsync method itself!