Loading multiple assetbundles from server

I’ve been trying to setup a AssetBundle Loader system for our project, but the documentation about this is confusing and I’m still not sure how or if I can setup the system the way I want to.

I want to store several prefabs in one AssetBundle each. So, AssetBundle X stores Prefab X.

I was able to get this to work in a simple sample script:

public class Loader : MonoBehaviour
{
    private AssetBundleCreateRequest bundleRequest;
    private UnityWebRequest request;
    private bool loaded;

    private void Start()
    {
        request = UnityWebRequest.GetAssetBundle(AppConfig.ASSETBUNDLE_URL + "myBundle/1");
        request.SendWebRequest();
    }

    private void Update()
    {
        if (!request.isDone || loaded){
            return;
        }
        var bundle = DownloadHandlerAssetBundle.GetContent(request);
        var myGameObject = Instantiate(bundle.LoadAsset("MyPrefab")) as GameObject;
        loaded = true;

    }
}

However it worked only for one bundle and only If I specify the name of the prefab, in that scene. I wanted to load all the assetsBundles in a “loading” scene to then instantiate the prefabs in the next scene.

TLDR:

  • How do I save assetbundles for later use in the app
1 Like

I’m doing pretty much the same thing in my project.

The official tool from unity will do exactly what you’re after.

And following the Manual for works like a charm.

Since I posted this I finally understood what I was doing wrong. To make Unity cache asset bundles GetAssetBundle HAS TO have the version otherwise it will not cache it.

However, now I’m having a different issue related to the bundles. I created a coroutine to load one asset bundle and works fine. Then I called this coroutine for each bundlename in a list. When I do this only the first bundle works, when it tries to load the second one it keeps getting the reference to the first one.

private IEnumerator GetAssetBundleFromRemote(string bundleName)
    {
        var bundleUrl = Path.Combine(RemotePath, bundleName);
        var webReq = UnityWebRequest.GetAssetBundle(bundleUrl, 1, 0);
        var handler = webReq.downloadHandler as DownloadHandlerAssetBundle;
        yield return webReq.Send();

        if (webReq.responseCode == 0){
            Debug.Log(bundleName + "__>" + "Loading from cache");
        }else if (webReq.responseCode == 200){
            Debug.Log(bundleName + "__>" + "Loading from server");
        }

        Debug.Log(bundleName + "__>" + "Analizing response");
        var bundle = handler.assetBundle;
       
        if (bundle == null){
            Debug.Log(bundleName + "__>" + "No Bundle Found");
            yield break;
        }
       
        Debug.Log(bundleName + "__>" + "Bundle Found");
        Debug.Log(bundleName + "__>" + "Bundle Name: " + bundle.name);
        foreach (var assetName in bundle.GetAllAssetNames()){
            Debug.Log("Asset: " + assetName);
        }
        var prefab = bundle.LoadAsset<GameObject>(bundleName);

        if (prefab != null){
            Debug.Log(bundleName + "__>" + "Prefab Found");
            Instantiate(prefab, transform, false);

        }
        bundle.Unload(false);
       
        yield return new WaitForSeconds(3);
    }

When it tries to load the second bundle this code:

foreach (var assetName in bundle.GetAllAssetNames()){
            Debug.Log("Asset: " + assetName);
        }

Gives me the assets of the first bundle.

This bundles don’t have anything in common

having same issue

Could it be that for subsequent calls it loads the same bundle from cache?
Try using an overload that takes a cached bundle name and make sure that name is unique for each bundle:

i am using WWW for downloading assetbundle from google drive. not unitywebrequest . WWW is working fine for 1 asset bundle with size less then 100mb , but when it exceeds 100mb its giving downloading error. but when i divide 1 into 2 asset bundle to reduce size problem it download both but show error if i try to get 2nd asset bundle.

void Awake()
    {
        if (Application.isEditor && removeCache)
            Caching.ClearCache();

        StartCoroutine(GetAssetBundle());
    }
   
    IEnumerator GetAssetBundle()
    {
        www = new WWW[url.Length];
        for (indexOfDownloadableFiles=0; indexOfDownloadableFiles < url.Length; indexOfDownloadableFiles++)
        {
             Debug.Log("Dowloading Started");

           
            www[indexOfDownloadableFiles] = WWW.LoadFromCacheOrDownload(url[indexOfDownloadableFiles], version );
           
            yield return www[indexOfDownloadableFiles];

            if (www[indexOfDownloadableFiles].error != null)
            {
                //if error in downloading asset bundle show error popup
                if (errorDownloadDb)
                    errorDownloadDb.SetActive(true);
                yield break;

                throw new Exception("WWW download had an error: " + www[indexOfDownloadableFiles].error);
            }
           
          

       
            AssetBundle assetBundle; assetBundle = www[indexOfDownloadableFiles].assetBundle;
      
            if (!assetBundle && errorDownloadDb)
            {
                errorDownloadDb.SetActive(true);
                yield break;
            }

            if (canLoadScene)
            {
                LoadSceneMethod(assetBundle);
            }
            else
            {

                if (prefabsName.Length > 0)
                {
                   
                    //instantiating prefabs
                    foreach (string prefabName in prefabsName)
                    {
                        Debug.Log("PrefebName" + prefabName);
                        AssetBundleRequest assetLoadRequest = assetBundle.LoadAssetAsync<GameObject>(prefabName);
                        GameObject AssetBundleObj = Instantiate(assetLoadRequest.asset) as GameObject;
                        AssetBundleObj.SetActive(true);
                        Debug.Log("AssetBundleObj: " + AssetBundleObj.name);
                    }
                }
                Debug.Log("BundleName: "+assetBundle.name);
               
                assetBundle.Unload(false);
                www[indexOfDownloadableFiles].Dispose();

                 Debug.Log( " Spawned");

            }
        }
            if (showContinue && continueButtonSplash)
            {
                continueButtonSplash.SetActive(true);
            }

            if (loadingObjGameplay)
                loadingObjGameplay.SetActive(false);
           
       
    }

That’s the error that i’m getting…

I was stuck in the same problem,
seems that you have to give a different name to the cached assetbundle, through the CachedAssetBundle structure

...
CachedAssetBundle cachedAssetBundle = new CachedAssetBundle();
        cachedAssetBundle.name = uniqueName;
...
UnityWebRequest uwr = UnityWebRequestAssetBundle.GetAssetBundle(mUri, cachedAssetBundle, 0);
...

because internally, seems that filenames are identical (filename is used as key along the hash number)