Search Unity

Joining Sync Code With Async Addressables

Discussion in 'Addressables' started by TheRatCircus, Oct 19, 2019.

  1. TheRatCircus

    TheRatCircus

    Joined:
    Aug 24, 2013
    Posts:
    2
    I took a look at the addressables package just recently to see if it might be a replacement for a hacked-together system I was using to hold template data objects during runtime.

    I like the package's pitch, and did some feasibility testing to see if I could migrate, but got concerned when I tried to test the system using my debugging console. The console works by invoking a callback in a Dictionary, and printing whatever the callback returns: "not enough arguments", "made you invincible", etc. With an asynchronous function, I can't just have the asset returned, so I either need to pass a callback to LoadAssetAsync().Completed, use a Coroutine, or use an async function. None of these allow for me to fulfill the requirements of this:

    Code (CSharp):
    1. public static string GiveItem(string[] args)
    2.         {
    3.             if (args.Length != 1)
    4.                 return "Please pass only 1 argument.";
    5.  
    6.             ScrollData scroll;
    7.             Database.GetDataObject("Scroll_MagicBullet",
    8.                 (ScrollData s) =>
    9.                 {
    10.                     scroll = s;
    11.                     Game.GetPlayer().AddItem(new Item(scroll));
    12.                 });
    13.  
    14.             return $"Giving {scroll}...";
    15.         }
    16.  
    17. public static void GetDataObject<T>(string address, Action<T> callback)
    18.             where T : IDataObject
    19.         {
    20.             Addressables.LoadAssetAsync<T>(address).Completed +=
    21.                 (AsyncOperationHandle<T> handle) =>
    22.                 {
    23.                     callback.Invoke(handle.Result);
    24.                 };
    25.         }
    26.  
    27.  
    Because the return will not fall in line behind the callback. The console not working doesn't break my whole project, but what I gather from this is that somewhere in any given call stack, one method has to be synchronous, at which point a race condition is created.

    Is there some clever pattern I'm missing which will let me load addressables without worrying about what happens elsewhere?
     
    tonytopper likes this.
  2. Favo-Yang

    Favo-Yang

    Joined:
    Apr 4, 2011
    Posts:
    464
    The alternative approach is using await op.Task, so you can chain async in a sync style function.
     
  3. TheRatCircus

    TheRatCircus

    Joined:
    Aug 24, 2013
    Posts:
    2
    I was expecting to need to do something like this; I was just hoping I wouldn't have to start converting a large portion of my codebase to asynchronous just for one feature.
     
    Last edited: Oct 20, 2019
    TextusGames likes this.
  4. davidla_unity

    davidla_unity

    Unity Technologies

    Joined:
    Nov 17, 2016
    Posts:
    763
    Hey @InfiniteCastor you might also check out https://github.com/Unity-Technologi...ced/Sync Addressables/Assets/SyncAddressables which is our sample on how to create custom Resource Providers that loads synchronous. It may be that you can drop these providers into your project, update your Addressable groups to use these providers and have everything work.

    I will say, currently an Addressable group can only use one Asset Provider and one Asset Bundle Provider at a time. So if you need something specific loaded synchronously you'll probably want to add them to their own "synchronous" group.

    Hope that helps!
     
  5. KB73

    KB73

    Joined:
    Feb 7, 2013
    Posts:
    234
    Hi David, we're trying to use the example in github, we're on Addressables 1.2.4 + Unity 2019.2.9 - there are some compile issues with the api ( providerTypes etc ) in the example.

    We tried to work around the compile issues but not sure if our fixes are sufficient

    Note: Every time we load an asset via SyncAddressables.LoadAsset<GameObject> it fails in the op.IsDone exception

    Is there something else we need to do?

    I am in fast mode, we have tagged the group as SyncBundledAssetProvider and SyncBundleProvider

    * Actually it seems the Instantiate flow works but the LoadAsset Sync does not work in the example - seems actually SyncFast needs to be on, our bad...just testing more now.
    thanks
     
    Last edited: Oct 21, 2019
    twhittaker likes this.
  6. davidla_unity

    davidla_unity

    Unity Technologies

    Joined:
    Nov 17, 2016
    Posts:
    763
    Hey @KB73 do you mind posting a little more information? What exception are you seeing get thrown when trying to access the op.IsDone property? How exactly are you using SyncAddressables.LoadAsset<GameObject> ? Do you mind sharing some of that code so I can check it out?
     
  7. KB73

    KB73

    Joined:
    Feb 7, 2013
    Posts:
    234
    Hey David, it was our bad, we hadn't set SyncFast in the Addressables Settings but

    SyncAddressables.Instantiate worked in 'Fast' mode, SyncAddressables.Load didn't

    Once we set to SyncFast mode they both work fine in the Editor.

    The only thing we had to do for Addressables 1.2.4 is fix up this code in the SyncFastModeBuild.cs

    Edits in bold to get it to compile

    On device, we're still seeing the 'Exception: Sync LoadAsset failed to load in a sync way!' - still investigating

    thanks

    protected override string ProcessGroup(AddressableAssetGroup assetGroup, AddressableAssetsBuildContext aaContext)
    {

    var errorString = string.Empty;

    PlayerDataGroupSchema playerSchema = assetGroup.GetSchema<PlayerDataGroupSchema>();
    if (playerSchema != null)
    {
    m_legacy = CreateLocationsForPlayerData(playerSchema, assetGroup, aaContext.locations, null);
    return errorString;
    }

    var allEntries = new List<AddressableAssetEntry>();
    foreach (var a in assetGroup.entries)
    a.GatherAllAssets(allEntries, true, true, true);

    var typeName = typeof(SyncAssetDatabaseProvider).FullName;
    foreach (var a in allEntries)
    a.CreateCatalogEntries(aaContext.locations, false, typeName, null, null, null);

    return errorString;
    }
     
    twhittaker and davidla_unity like this.
  8. KB73

    KB73

    Joined:
    Feb 7, 2013
    Posts:
    234
     
  9. errorcode

    errorcode

    Joined:
    Sep 12, 2013
    Posts:
    5

    Hello! I also get the same message in the example and in my project.
    'Exception: Sync LoadAsset failed to load in a sync way!'

    Unity version 2018.4.6f1
    Addressables version 1.2.4
     
  10. davidla_unity

    davidla_unity

    Unity Technologies

    Joined:
    Nov 17, 2016
    Posts:
    763
    It may be that we need to revisit this example. SyncAddressables still uses
    Code (CSharp):
    1. Addressables.LoadAssetAsync<TObject>(key);
    to actually call into Addressables so we may have changed something a little further down that's preventing this from working correctly. @unity_bill might be able to shed some light on the problem.
     
  11. khalid_mightybear

    khalid_mightybear

    Joined:
    Sep 10, 2017
    Posts:
    36
    is it still not working correctly on device?

    What's the actual setup to get it working on device?
     
    Last edited: Apr 3, 2020
  12. sameng

    sameng

    Joined:
    Oct 1, 2014
    Posts:
    184
    Any update on this?
     
  13. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
  14. TrueNoob141

    TrueNoob141

    Joined:
    Sep 18, 2019
    Posts:
    30
  15. tonytopper

    tonytopper

    Joined:
    Jun 25, 2018
    Posts:
    226
    I am struggling with the same problem as the OP. I am a bit disappointed in the Addressable API design and examples. It doesn't correlate well to existing paradigms in other languages and frameworks in my opinion. Making the learning curve frustrating.

    Is this some sort of limitation with C#? This is trivial to do in any Swift or JavaScript framework I've worked with.

    It seems to me that from a high level being able to load and then return data should not have such levels of friction. That should be a full stop. This makes it really hard to move from the older, no longer recommended system, to this new system.

    Seems like Unity is recommending this new solution too soon.
     

    Attached Files:

    twhittaker likes this.
  16. TreyK-47

    TreyK-47

    Unity Technologies

    Joined:
    Oct 22, 2019
    Posts:
    1,822
    Howdy all! Wanted to pass along a bit of info from the team. They are working on sync versions of our APIs, but don't have a firm release date to share at this time. Stay tuned!
     
  17. votagus

    votagus

    Joined:
    Dec 13, 2016
    Posts:
    15
    Is there any update on this? We want to use this for our project, but we can't change the whole flow to make it async.
     
  18. brunocoimbra

    brunocoimbra

    Joined:
    Sep 2, 2015
    Posts:
    679
    It's been there has been a few versions already
     
  19. votagus

    votagus

    Joined:
    Dec 13, 2016
    Posts:
    15
    Hmm, but I have the last version available for 2020.3.x and all the sync versions (LoadAsset, etc) are marked as obsolete.
     
  20. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,925
    votagus likes this.