Configuring Addressables for iOS App Slicing

We’re trying to configure an iOS game for app Slicing using Addressables, but we’re encountering an issue loading the bundles. We’ve found a workaround, but it’s cumbersome, and I’m wondering if there’s a better way to set things up.

The issue that we’re having is that when an asset bundle is requested the “res://” URL is interpreted as a remote http request which fails since the URL is intended to reference an iOS Asset Catalog. We need the “res://” URL to be resolved against the asset catalog, not using an NSURLSession.

While our use case has to do with Slicing, our investigation indicates that a similar issue would happen with ODR.

Our Setup

We’re using Addressables V 1.19.18 (but can also reproduce this with V 1.19.15) and Unity 2021.2.8f1. I have an Addressables profile that sets LocalBuildPath to a location in our Asset database, and LocalLoadPath = “res://”. This prevents the normal installation of the AssetBundles into the Data folder of our Xcode project (which is what we want). Our groups were originally configured to use AssetBundleProvider (the default) but our workaround has required us to change that.

To create an Asset Catalog I assign a callback to UnityEditor.iOS.BuildPipeline.collectResources that generates Resource instances for all of the bundles saved in the previous step.

The Issue

All of the above works, but when we run the project we get a lot of NSURLRequest errors and none of the bundles are able to load. Digging into this a bit we discovered that ResourceManagerConfig.ShouldPathUseWebRequest() returns true for “res://” requests because they contain “://”. If AssetBundleProvider is expected to work with Asset Catalogs, then ShouldPathUseWebRequest() should check to see if the platform is iOS, and if it is return false for requests that start with “res://”.

Workaround

Our workaround is a bit more complicated, since ResourceManagerConfig.ShouldPathUseWebRequest() is static and difficult to patch. We implemented our own ResourceProvider that is essentially just a copy of AssetBundleProvider, with the following check in GetLoadInfo():

if (path.StartsWith("res://"))
    loadType = LoadType.Local;

This works, and the bundles load properly, but it’s a hack and requires a lot of duplicate code. For deployment we’re considering cloning the Addressables package and just fixing ResourceManagerConfig. But if we could avoid all of this using an existing ResourceProvider or a different configuration it would be cleaner.

FYI I’ve uploaded a fix for this issue to a forked repo. I’d submit a PR, but the GitHub repo is non official, so there’s nowhere for a PR to go.

I’m still wondering if this is the best way to deal with this issue, or if there is some other configuration option that I’m missing. I’m currently wrestling with getting the thinned variants to resolve properly. I’m trying to implement multiple catalogs for the different thinning options so that the correct asset in the AssetCatalog is queried based on the thinning options.

Just an update in case someone lands here via a search. I added code to Addressables to generate the Resources that define the Xcode asset catalog. Details on how to use this are in Readme.md. It is possible to define several ‘variant groups’ to have multiple criteria for slicing different kinds of assets.

1 Like