How to download an assetBundle from server and use it in app?

I have created assetBundles-5 prefab models were given the name ‘kitchen’ and around 3 prefab models the name ‘furniture’ for the created assetbundles.The code I used for making AssetBundles is as follows and kept in the Assets/Editor folder.

public class Assetcreate : Editor
{
    [MenuItem("Assets/Build Home Assets")]
    static void BuildKitchenAssets()
    {
        BuildPipeline.BuildAssetBundles("/Users/ar/Desktop/HomeBundles",BuildAssetBundleOptions.ChunkBasedCompression,BuildTarget.StandaloneOSX);
    }
}

In the desktop I have the created AssetBundles.I upload these files in the server using Filezilla(with Transfer>TransferType>Binary).
The code for downloading the assets are as follows,

public int version=0;
public string url=http://safebuild.net/hari/bundle/;
public string AssetName="Chair-Almera";

void Start()
{
        StartCoroutine(GetBundles());
}

IEnumerator GetBundles()
{

while (!Caching.ready)
            yield return null;

        //Load the assetBundle file from Cache if it exists with the same version or download and store it in the cache.
        using (WWW www = WWW.LoadFromCacheOrDownload(url, version))
        {
            yield return www;
            if(www.error!=null)
            {
                throw new Exception("WWW download error: "+www.error);
            }
            AssetBundle bundle = www.assetBundle;
            if(AssetName==" ")
            {
                Instantiate(bundle.mainAsset);
            }
            else
            {
                //GameObject go=bundle.LoadAsset<GameObject>(AssetName);
                GameObject go = bundle.LoadAsset(AssetName) as GameObject;
                Instantiate(go);
            }

            bundle.Unload(false);
        }

    }

Now few errors occured when I click play in the editor and no prefabs came on the Game view.

1)Error while downloading Asset Bundle: Failed to decompress data for the AssetBundle ‘http://safebuild.net/hari/bundle/’.

2)/Users/ar/Documents/Unity Projects/Kitchen/Assets/Scripts/ABLoadOnline.cs(26,26): Warning CS0618: ‘WWW’ is obsolete: ‘Use UnityWebRequest, a fully featured replacement which is more efficient and has additional features’ (CS0618) (Assembly-CSharp)

3)/Users/ar/Documents/Unity Projects/Kitchen/Assets/Scripts/ABLoadOnline.cs(29,29): Warning CS0618: ‘AssetBundle.mainAsset’ is obsolete: ‘mainAsset has been made obsolete. Please use the new AssetBundle build system introduced in 5.0 and check BuildAssetBundles documentation for details.’ (CS0618) (Assembly-CSharp)

How to download the AsssetBundles files and download for IOS/Android persistant path.I want an efficient way to do this.Should I download all the assetbundle files from the server (folder structure) to the device path?If already downloaded, dont download the bundle again.At the same time if I have added new models to the ‘kitchen’ assetbundle it has to check and update the bundle.

The link points to a web page listing your bundles. You should be downloading the bundles themselves. Also, use UnityWebRequest istead of old WWW.

Both WWW and UnityWebRequest give you ability to use built-in caching system.

2 Likes

For kitchen assetbundle I have to give

public string url="http://safebuild.net/hari/bundle/kitchen";

So if I have multiple assetbundles I have to give multiple links ? Also
I tried the following code but this is not cached.

using(UnityWebRequest uwr=UnityWebRequestAssetBundle.GetAssetBundle(url,0))
{
yield return uwr.SendWebRequest();
if (uwr.error != null)
{
throw new Exception("WWW download error: "+uwr.error);
}
AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(uwr);
if(AssetName==" ")
{
Instantiate(bundle.mainAsset);
}
else
{
GameObject go = bundle.LoadAsset(AssetName) as GameObject;
Instantiate(go);
}
}

I came across the following code

public static Networking.UnityWebRequest GetAssetBundle(string uri, CachedAssetBundle cachedAssetBundle, uint crc);

What is CachedAssetBundles cachedAssetBundle ?Should I give a persistent data path there? Every time I update AssetBundle I need to increment crc?

using(UnityWebRequest uwr=UnityWebRequestAssetBundle.GetAssetBundle(url,XXXXXXX,0))

Read documentation on UnityWebRequest.GetAssetBundle. It doesn’t cache if only URL is provided, but if you provide hash or CRC, it does save bundle on disk and reloads it the next time.
If you have multiple bundles that you will update and don’t want to update your app when you do, you should be hosting information about the bundles as well, have a look at asset bundle manifest.

1 Like

I copied the crc number from manifest file and gave it as uint and tried the code below.

    public uint crc= 3720593779;//copied from http://safebuild.net/hari/bundle/kitchen.manifest
    public string url;
    public string AssetName;
using(UnityWebRequest uwr=UnityWebRequestAssetBundle.GetAssetBundle(url,crc))
        {
            yield return uwr.SendWebRequest();


            if (uwr.error != null)
            {
                throw new Exception("WWW download error: "+uwr.error);
            }
            AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(uwr);
            if(AssetName==" ")
            {
                Instantiate(bundle.mainAsset);
            }
            else
            {
                //GameObject go=bundle.LoadAsset<GameObject>(AssetName);
                GameObject go = bundle.LoadAsset(AssetName) as GameObject;
                Instantiate(go);
            }
          
        }

This is still downloading but not caching.Any tutorials?
Are these the steps given below?
Step 1-Download the manifest file into Application.Persitentpath.
Step 2-Load the manifest
Step 3-Get the crc or hash
Step 4-Download assets using uri and newly obtained crc/hash

How do you check if bundle is cached or not?

using (WWW www = [WWW.LoadFromCacheOrDownload(url](http://WWW.LoadFromCacheOrDownload(url), version))
Using WWW it required only this much but for UnityWebRequest it is a bit confusing.Need to add versions?

It’s the same with UnityWebRequest, please read carefully:

https://docs.unity3d.com/ScriptReference/Networking.DownloadHandlerAssetBundle-ctor.html
I read and tried this script.Similiar one.
For version I have given zero in the inspector.So if I update the assetbundles then I need to increment version?

IEnumerator DownloadBundles()
    {
        using (var uwr = new UnityWebRequest(url, UnityWebRequest.kHttpVerbGET))
        {
            uwr.downloadHandler = new DownloadHandlerAssetBundle(url,version,0);
            yield return uwr.SendWebRequest();
            AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(uwr);
            if (AssetName == " ")
            {
                Instantiate(bundle.mainAsset);
            }
            else
            {
                //GameObject go=bundle.LoadAsset<GameObject>(AssetName);
                GameObject go = bundle.LoadAsset(AssetName) as GameObject;
                Instantiate(go);
            }

            bundle.Unload(false);
        }
    }

With version being zero it is not caching, as documented. Yes, if you update the bundle, you have to increment the version, otherwise you’ll be loading the same bundle from cache.

I have given ‘0’ for version in the inspector,I checked the cache folder on mac and I found a Unity folder which contains the cached data for assetbundle.That means it is caching.Once I alter the asset names I am getting different prefabs which I stored as assetbundle on the server instantly.Earlier for each asset names given I had to wait for every single one of them to download.

Unity caches by given URL. If you reupload assets with different names and cache them with version 0, it will download the ‘new’ assetbundle.

If you want to update an assetbundle on the server (and obviously, don’t want to change the name) your client has to know if it changed. This is done by prodiving the manifest and downloading that first, then you can check the hash and supply it to the unity web request, so it knows if the hash changed it needs to redownload the assetbundle.