Search Unity

Resolved All DLC addressable bundles required when loading first addressable

Discussion in 'Addressables' started by jeppe79, Dec 29, 2021.

  1. jeppe79

    jeppe79

    Joined:
    Sep 17, 2019
    Posts:
    76
    The project I'm working on will be using addressable bundles as purchasable DLC.
    Meaning the app should be able to run without these.

    For some reason they all need to be present in the device's DLC folder when I try to load the first addressable.
    If I remove any bundles, however unrelated they are to that first addressable call, I get this error.
    Code (CSharp):
    1. Unable to open archive file: (path to bundle)/bundle_name.bundle
    2. Failed to read data for the AssetBundle 'bundle_name.bundle'.
    3. RemoteProviderException : Invalid path in AssetBundleProvider:
    The assets in the addressable groups/bundles are not dependent on eachother between different groups/bundles.

    These are my bundle settings. (see picture)
    I pack them together so all assets in a group is packed together in a bundle (some for DLC file and some for default assets needed for the main app to run).
    The load mode is Request Asset and Dependencies, so as far as I understand, this should only load the requested asset from the addressable group upon an actual request, not the whole package, and not without a request.

    So I don't understand what I am missing.
    Any insight here would be deeply appreciated.

    upload_2021-12-29_23-8-47.png
     
  2. LuGus-Jan

    LuGus-Jan

    Joined:
    Oct 3, 2016
    Posts:
    179
  3. jeppe79

    jeppe79

    Joined:
    Sep 17, 2019
    Posts:
    76
    Hi, big thanks!

    I ran into some problems.

    Ok so, It works so far that I managed to include some main addressable asset group bundles in the main build and exclude one of them, and the app worked fine.

    But adding the excluded package to the load path didn't make any difference.
    The app still complained about that the path the addressable was trying to load from didn't lead to anything.
    Code (CSharp):
    1. UnityEngine.AddressableAssets.InvalidKeyException: Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown., Key='addressable-path-string', Type=UnityEngine.TextAsset
    2. ArgumentNullException: Value cannot be null.

    What I have done:

    1. Added and installed the modified Addressable repo
    2. Created the new build mode for Multiple catalogs
    3. Assigned this new data builder to the list of available Build and Playmode Scripts in the AddressableAssetSettings object.
    4. Created a new CatalogContentGroup
    5. Assigned this new catalog content group to the list of additional catalogs in the MultipleCatalogs data builder.

    The above mentioned steps were pretty straight forward, I think my error is somehere in the next steps.

    6. I set this build path to a folder outside of the Assets folder, but still inside in the project folder.
    7. Set the runtime load path to the DLC folder of the device Android/obb/appname/
    8. Set the Catalog Name to something unique (Not the asset group name)
    9. In addressable profiles I set the build and load path to the default, I'm thinking this is for the addressable groups that should be included in the main build file.
    Build path: [UnityEngine.AddressableAssets.Addressables.BuildPath]/[BuildTarget]
    Load path: {UnityEngine.AddressableAssets.Addressables.RuntimePath}/[BuildTarget]
    10. Saved the project, then in Addressables I did, Build -> Clean build -> All
    11. Build -> New build -> Default Build Script - Multiple Catalogs
    12. File -> Build Settings -> Build

    In the dlc-package folder (Build path of DLC content) I got the UniqueCatalogName.json and the addressable asset bundle file
    I placed them both in the DLC folder of the target device mentioned above, but yea, that didn't help.


    Is there anything sticking out to you that might look like a problem?



    /J
     
    Last edited: Jan 4, 2022
  4. LuGus-Jan

    LuGus-Jan

    Joined:
    Oct 3, 2016
    Posts:
    179
    @jeppe79

    Exactly the opposite! That's what the 'vanilla' implementation of Addressables requires you to do, along with a bunch of disadvantages (increased build time and size). With the Multiple catalog setup, you don't need to worry about ticking boxes that belong to which part of your build, instead, they are managed by the multiple-catalog system and will set the Addressables group enabled, if relevant to the build, move it out of the final build to a separate location along with an extra catalog.json file that only entails those assets.

    It basically boils down to this:
    • First of all, tick all of the 'Include in build' boxes of the Addressables groups that you want to belong in your base game. A main catalog is created, as it would by default in vanilla Addressables, which contains the assets that you would like to have at all times.
    • In the Multiple Catalogs data builder, assign additional catalogs per DLC package that you have, and in each of those additional catalog objects, you assign which groups belong to that DLC package specifically.
    • The multiple catalog building system will include every Addressables group in the build that is either already ticked (main catalog), or is set to be included by one of the additional defined catalogs. During the build, Addressables will resolve all of the dependencies, and after that is done, the multiple catalog system will start extracting out the content as defined by each additional catalog and move them to the defined build path for that catalog. After that, Addressables will continue and generate the main catalog for the left-over content, which it will consider the main assets of the game.

    I have no experience at all with mobile platforms, so I don't know what the limitations on that platform are in terms of how much control you can exert over where content is placed in the end. I don't see any reason why the load paths can't be the same (just make sure that in each additional catalog object, you set a unique catalog name). It used to be that it created a literal `catalog.json` file, so that would collude between DLC packages, but if each catalog name is unique, I guess it would be fine.

    Hope that explains it a bit. :)
     
    jeppe79 likes this.
  5. dirty-rectangle

    dirty-rectangle

    Joined:
    Apr 23, 2015
    Posts:
    78
    have you looked at the build layout report https://docs.unity3d.com/Packages/com.unity.addressables@1.16/manual/DiagnosticTools.html

    Even if the assets being loaded don't have dependencies, if the asset bundles they are in do have dependencies, it will still require them to be local before the asset can be loaded.
     
  6. jeppe79

    jeppe79

    Joined:
    Sep 17, 2019
    Posts:
    76
    Sorry for late reply, I'm having breaking issues with 1.19.11 (actually 1.18.13 and up) that I need to figure out before giving this a real go.

    I'll post back soon!
     
  7. jeppe79

    jeppe79

    Joined:
    Sep 17, 2019
    Posts:
    76
    @LuGus-Jan

    I'm doing it like you describe, but I'm not getting it work.
    It seems I edited the original post while you were replying, perhaps there are some clues there on what could be wrong?

    From what I understand, everything should be ticked as include in build (base + optional DLC)

    The Addressables builds without errors and the game builds fine too and no errors while playing around with other Addressable assets that are included in the build, but as soon as I hit that DLC area, the exception is flying.

    What baffles me a bit, if you look at the error message I'm getting, it's not complaining about not finding the asset bundle file, even if I don't add the asset bundle + catalog.json to the target device/folder.
    It only seems to complain that there is nothing at the Addressable path/label.

    Can I debug this in your custom package somehow?

    Code (CSharp):
    1. 01-12 21:34:39.758 10478 10499 E Unity   : UnityEngine.AddressableAssets.InvalidKeyException: Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown., Key=root/sandbox/level1/outlook/bonusarea, Type=UnityEngine.TextAsset
    2. 01-12 21:34:39.758 10478 10499 E Unity   :
    3. 01-12 21:34:39.769 10478 10499 E Unity   : ArgumentNullException: Value cannot be null.

    Also, you didn't mention this so I'm guessing it should be left alone, I just want to exhaust as many possibilities for errors as I can.
    The actual addressable group has it's own build/load path here.
    Should it match the new catalog build/load path or should I just leave it as it is?

    upload_2022-1-12_22-10-55.png
     
  8. jeppe79

    jeppe79

    Joined:
    Sep 17, 2019
    Posts:
    76
    @LuGus-Jan

    Hi, sorry to ping you, I just really need some help with your Addressables solution.

    I have started a new project from scratch to isolate it, and seem to get the same behaviour.
    Added screenshots of the setup below, if you could look at them and see if something looks out of place.

    The load path seems to be accessible and valid (obb/project is the dlc/expansion folder for Android), for whenI do a normal build (single catalog) with the custom buildpath/loadpath in the actual addressable asset group and add/remove the DLCAsset bundle from the obb/project folder on the device, that works (adding) and when removing it I get an exception of missing bundle file.

    But with the below settings I only get this error message (Notice the logs):

    01-19 09:43:20.805 5351 5372 I Unity : Base addressable is loaded
    01-19 09:43:20.805 5351 5372 I Unity :
    01-19 09:43:24.156 5351 5372 E Unity : UnityEngine.AddressableAssets.InvalidKeyException: Exception of type 'UnityEngine.AddressableAssets.InvalidKeyException' was thrown., Key=knight, Type=UnityEngine.Sprite
    01-19 09:43:24.156 5351 5372 E Unity :
    01-19 09:43:24.157 5351 5372 I Unity : DLC addressable is loaded
     

    Attached Files:

    • 1.jpg
      1.jpg
      File size:
      287.2 KB
      Views:
      295
    • 2.jpg
      2.jpg
      File size:
      272.3 KB
      Views:
      309
    • 3.jpg
      3.jpg
      File size:
      384.8 KB
      Views:
      308
    • 4.jpg
      4.jpg
      File size:
      283.6 KB
      Views:
      304
    • 5.jpg
      5.jpg
      File size:
      137.7 KB
      Views:
      290
    Last edited: Jan 19, 2022
  9. jeppe79

    jeppe79

    Joined:
    Sep 17, 2019
    Posts:
    76
    Forgot the Addressable Settings screenshot.
    Here it is.
     

    Attached Files:

    • 7.jpg
      7.jpg
      File size:
      397 KB
      Views:
      270
  10. LuGus-Jan

    LuGus-Jan

    Joined:
    Oct 3, 2016
    Posts:
    179
    Hi @jeppe79

    Sorry for the delay in response. I meant to reply earlier, but I tend to take quite a while to write up a reply and something forget I had things left open...

    Regarding your issue, it's not something I see in the piece of code you display, but are you also actually loading in the additional catalog using
    Addressables.LoadContentCatalogAsync()
    ? Since the content is split over multiple catalogs, your DLC assets aren't known to the system until you also load in the DLC catalog. The rest of your settings seem to be set alright, and I see your DLC data and catalog are placed separately. So that seems to be good. :)

    For example, a piece of code out of our project to load in the DLC pack/content:

    Code (CSharp):
    1. string catalogPath = Path.Combine(bundleLocation, "NightFever.json");
    2.  
    3. AsyncOperationHandle<IResourceLocator> loadingHandle = Addressables.LoadContentCatalogAsync(catalogPath);
    4. yield return loadingHandle;
    5.  
    6. if (loadingHandle.Status == AsyncOperationStatus.Succeeded)
    7. {
    8.    // Catalog successfully loaded!
    9.    onBundleLoaded.InvokeIfNotNull(this);
    10. }
    Once this is done, the content should be available.

    Note: the
    Addressables.LoadContentCatalogAsync()
    method has an overload to define a 'provider suffix'. Don't use this one, as it seems like this separates the dependencies from each other, and might be problematic if your DLC assets (partially) rely on the assets being available in the base game. (This little thing cost me days of searching why my content was running into dependency issues)
     
    Last edited: Jan 19, 2022
    jeppe79 likes this.
  11. jeppe79

    jeppe79

    Joined:
    Sep 17, 2019
    Posts:
    76
    Hi @LuGus-Jan

    Many, many thanks!

    You are absolutely correct, I didn't load in the additional catalog and that was the problem.
    It works now and it is absolutely amazing!
    I really hope Unity adopts this into their Addressables package.

    I did have one issue with the load path in the additional catalog.

    It didn't seem to understand that it was a variable from the Addressables profile.
    But it worked when I wrote it out in a full path without the brackets.
    sdcard/Android/obb/com.TestCompany1.TestProject1

    It puzzles me as the [NewBuildPath] variable works fine.

    Notice how the [NewLoadPath] being regarded as part of the location string.
    Am I using this wrong or would you consider this a bug?


    01-19 21:43:54.273 11463 11545 E Unity : Unable to open archive file: [NewLoadPath]/dlcasset_assets_all_2beaa71a005dca138c87d1fd8a91cca2.bundle
    01-19 21:43:54.273 11463 11545 E Unity :
    01-19 21:43:54.282 11463 11484 E Unity : Failed to read data for the AssetBundle 'dlcasset_assets_all_2beaa71a005dca138c87d1fd8a91cca2.bundle'.
    01-19 21:43:54.282 11463 11484 E Unity :
    01-19 21:43:54.286 11463 11484 E Unity : RemoteProviderException : Invalid path in AssetBundleProvider: '[NewLoadPath]/dlcasset_assets_all_2beaa71a005dca138c87d1fd8a91cca2.bundle'.
    01-19 21:43:54.286 11463 11484 E Unity :
    01-19 21:43:54.288 11463 11484 E Unity : OperationException : GroupOperation failed because one of its dependencies failed
    01-19 21:43:54.288 11463 11484 E Unity : RemoteProviderException : Invalid path in AssetBundleProvider: '[NewLoadPath]/dlcasset_assets_all_2beaa71a005dca138c87d1fd8a91cca2.bundle'.
    01-19 21:43:54.288 11463 11484 E Unity :
    01-19 21:43:54.298 11463 11484 E Unity : System.Exception: Dependency Exception ---> UnityEngine.ResourceManagement.Exceptions.OperationException: GroupOperation failed because one of its dependencies failed ---> UnityEngine.ResourceManagement.Exceptions.RemoteProviderException: Invalid path in AssetBundleProvider: '[NewLoadPath]/dlcasset_assets_all_2beaa71a005dca138c87d1fd8a91cca2.bundle'.
    01-19 21:43:54.298 11463 11484 E Unity : --- End of inner exception stack trace ---
    01-19 21:43:54.298 11463 11484 E Unity : --- End of inner exception stack trace ---
     

    Attached Files:

    • b1.jpg
      b1.jpg
      File size:
      77 KB
      Views:
      291
    • b2.jpg
      b2.jpg
      File size:
      48.9 KB
      Views:
      291
    • b3.jpg
      b3.jpg
      File size:
      51.5 KB
      Views:
      281
    Last edited: Jan 20, 2022
  12. LuGus-Jan

    LuGus-Jan

    Joined:
    Oct 3, 2016
    Posts:
    179
    @jeppe79

    That's something I'll have to investigate. I currently don't use this myself, but I thought this should work. However, I've had mixed success with these custom variables myself. I'll try to make sure to come up with a definite answer.
     
  13. LuGus-Jan

    LuGus-Jan

    Joined:
    Oct 3, 2016
    Posts:
    179
    Hi @jeppe79 , it seems like it currently doesn't. I haven't had time to fully test this yet, but you could perform the following changes in the
    BuildScriptPackedMultipleCatalogs
    script. Replace, in the
    GetContentCatalogs
    method, the second foreach loop (the one iterating over all the locations) with the following piece of code:

    Code (CSharp):
    1. // Assign assets to new catalogs based on included groups
    2. var profileSettings = aaContext.Settings.profileSettings;
    3. var profileId = aaContext.Settings.activeProfileId;
    4. foreach (var loc in aaContext.locations)
    5. {
    6.     CatalogSetup preferredCatalog = catalogSetups.FirstOrDefault(cs => cs.CatalogContentGroup.IsPartOfCatalog(loc, aaContext));
    7.     if (preferredCatalog != null)
    8.     {
    9.         if (loc.ResourceType == typeof(IAssetBundleResource))
    10.         {
    11.             string filePath = Path.GetFullPath(loc.InternalId.Replace("{UnityEngine.AddressableAssets.Addressables.RuntimePath}", Addressables.BuildPath));
    12.             string runtimeLoadPath = preferredCatalog.CatalogContentGroup.RuntimeLoadPath + "/" + Path.GetFileName(filePath);
    13.             runtimeLoadPath = profileSettings.EvaluateString(profileId, runtimeLoadPath);
    14.  
    15.             preferredCatalog.Files.Add(filePath);
    16.             preferredCatalog.BuildInfo.Locations.Add(new ContentCatalogDataEntry(typeof(IAssetBundleResource), runtimeLoadPath, loc.Provider, loc.Keys, loc.Dependencies, loc.Data));
    17.         }
    18.         else
    19.         {
    20.             preferredCatalog.BuildInfo.Locations.Add(loc);
    21.         }
    22.     }
    23.     else
    24.     {
    25.         defaultCatalog.Locations.Add(loc);
    26.     }
    27. }
    This should evaluate your custom loadpath. Thanks for bringing this to my attention! I'll update the repo in time to get this added as well.

    Hope that helps. :)
     
    jeppe79 likes this.
  14. jeppe79

    jeppe79

    Joined:
    Sep 17, 2019
    Posts:
    76
    Hi @LuGus-Jan ,

    Your fix worked perfectly! :)
    Thanks a bunch for the quick response and great help, I really appreciate it.

    Also a big hand for your work on this feature, it saves a lot of resources in so many ways. :)
    It also made things possible in my project that else simply wouldn't be a viable option due to hardware limits.
     
    LuGus-Jan likes this.
  15. LuGus-Jan

    LuGus-Jan

    Joined:
    Oct 3, 2016
    Posts:
    179
    Hi @jeppe79

    Sorry, to bring up this thread again, since your issue is already resolved, but I wanted to let you know that I've added the little fix for the string evaluation of the Addressables variables, and updated the repo to be more friendly to use for any other/future projects where this functionality may be desired. :)

    Link to repo: https://github.com/juniordiscart/com.unity.addressables

    Thanks and kind regards!
     
    DREBOTgamestudio likes this.
  16. jeppe79

    jeppe79

    Joined:
    Sep 17, 2019
    Posts:
    76
    Hi @LuGus-Jan

    Awesome work! I will update asap. :)
    Thanks for letting me know!
     
  17. yusufalibrahim1994

    yusufalibrahim1994

    Joined:
    Nov 13, 2019
    Posts:
    2
    I've been trying for 2 days to figure out how to load textures from an OBB. I'm developing for the Quest 2/3 and I'm using the addressable package in LuGUs github, followed the steps in the github and I've set the load path for both the External Catalag Setup and Addressable Asset Group into sdcard/Android/obb/com.company.project/ and I unticked the split application binary in the project settings. I then did a clean build which outputs 3 things: APK, OBB and JSON. In the meta quest developer hub, I've only added the apk and obb since I get an api error when also adding the JSON. In the app, I can't load the textures from the OBB (although it does work in Unity and also it does work when building the APK alone without OBB). Note that I kept the asset file path in the meta quest developer hub empty. I used a 3rd party file explorer in my quest 3 to see if the OBB location is correct and it is correctly in Quest3/Android/obb/com.company.project/. Any insight?

    EDIT:
    I removed the LuGUs addressables and reinstalled it. I then tried not using multi-catalog, ticked split application binary and left build and load path as local, built it and it worked. Also, I just remembered that I had success of using multi-catalog last week with one of the builds but I have no idea what I did!
     
    Last edited: Oct 29, 2023