Search Unity

Loading AssetBundle's with the same name

Discussion in 'Asset Bundles' started by halilkayim, Oct 23, 2018.

  1. halilkayim

    halilkayim

    Joined:
    Feb 27, 2018
    Posts:
    21
    We have a growing number of AssetBundle's located in the cloud. We download these bundles at runtime and instantiate the prefabs inside them. Our content team seems to have bundled quite a few of these AssetBundle's with the same bundle name even though the files inside them are entirely different. When we try to download and load more than one of these AssetBundle's on the client side, Unity throws an error on the second and later bundles: "Error while getting Asset Bundle: The AssetBundle 'https://myserver.com/files/id/bundlename' can't be loaded because another AssetBundle with the same files is already loaded."

    Our loading code is as follows:
    Code (CSharp):
    1. DownloadOperation = UnityWebRequestAssetBundle.GetAssetBundle( _model.ModelFileUrl, Convert.ToUInt32(_model.UpdatedAt), 0).SendWebRequest();
    2.  
    3. DownloadOperation.completed += operation =>
    4. {
    5.     var webRequest = DownloadOperation.webRequest;
    6.     if (webRequest.isNetworkError || webRequest.isHttpError)
    7.     {
    8.         throw new Exception($"Error while downloading asset: {webRequest.error}");
    9.     }
    10.  
    11.     _assetBundle = DownloadHandlerAssetBundle.GetContent(webRequest); // this is the line that causes the error
    12.     if (!_assetBundle)
    13.     {
    14.         throw new Exception($"Could not get content from AssetBundle with ID: {_model.Id}");
    15.     }
    16.     // use _assetBundle to instantiate prefab
    17. }
    Right now, we can handle this error so no crashes happen, but we would like to know if there is a way to solve this without re-bundling the AssetBundle's with the same bundle name. Any insight on this would be much appreciated.
     
  2. DORNE

    DORNE

    Joined:
    Jul 4, 2017
    Posts:
    6
    I have the same problem and I don' know how to handle this error and avoid crashes. Could you tel me how you did it ?
    Thanks
     
  3. halilkayim

    halilkayim

    Joined:
    Feb 27, 2018
    Posts:
    21
    Unity's API doesn't seem to support this in any way, so we had to write a custom class AssetBundleManager which handles loading and caching AssetBundle's, so that we wouldn't attempt to load two bundles with the same name. As for the pre-existing bundles, unfortunately we had to re-bundle them all.
     
  4. Ryanc_unity

    Ryanc_unity

    Unity Technologies

    Joined:
    Jul 22, 2015
    Posts:
    223
    You need to switch to using this version of the GetAssetBundle API:

    Code (CSharp):
    1. public static Networking.UnityWebRequest GetAssetBundle(string uri, CachedAssetBundle cachedAssetBundle, uint crc);
    Reason:
    Asset bundle names can contain path notations
    My/AssetBundle1/prefabs
    and
    My/AssetBundle2/prefabs
    which is not something that can be determined from a URL automatically easily:
    https://mygames.com/mygame/bundles/My/AssetBundle1/prefabs
    vs
    https://mygames.com/mygame/bundles/My/AssetBundle2/prefabs
    . In both of those cases the cached asset bundle name becomes
    prefabs
    which is incorrect. The
    CachedAssetBundle
    struct resolves this issue by requiring you to provide the cached asset bundle name and hash instead of us pulling it from the URL. So you construct a
    CachedAssetBundle
    with the name
    My/AssetBundle1/prefabs
    and correct hash, and the cache will then store it using that name and hash and be able to distinguish it correctly from
    My/AssetBundle2/prefabs
    .
     
    jacksonbarnes and tkg_szaluga like this.
  5. tkg_szaluga

    tkg_szaluga

    Joined:
    Sep 7, 2018
    Posts:
    1
    Hi Ryanc_unity,
    Your answer got me excited because it's exactly what I need. However, it does not appear to work the way you describe - the downloaded bundle still uses a name derived from the url instead of the name provided with CachedAssetBundle, so I am still getting "Error while getting Asset Bundle: The AssetBundle 'https://myserver.com/files/id/bundlename' can't be loaded because another AssetBundle with the same files is already loaded.".
    The docs say that the name in CachedAssetBundle is "AssetBundle name which is used as the customized cache path.". I wonder if that means that it can only be used to cache more than one version of the bundle, but one still has to manually make sure only one of them is loaded at any given time...
     
  6. jacksonbarnes

    jacksonbarnes

    Joined:
    Sep 13, 2017
    Posts:
    15
    I've been trying to figure out the caching system but Im just a little confused on how to get the hash and the name of the asset bundle before it even gets downloaded with the .GetAssetBundle()? Like when you are constructing the CachedAssetBundle struct do you have to download the manifest for that asset bundle first then pull its hash and name THEN pass the cachedAssetBundle into the .GetAssetBundle(uri, cachedAssetBundle, 0)?