Write Downloaded AssetBundle to Local Storage

Hello! I am attempting something I haven’t seen on the forum or answers before…

I want to be able to upload assetbundles to my server and players be able to download and use them… easy enough. However, since it is a mobile game, I am trying to make it so that after you download it once, it saves it to Application.persistantDataPath/bundles so that I can load from there instead… I can make it detect if the bundle is downloaded or not, and pull from the right locations, I just can’t figure out how to make it copy the downloaded bundle…

I’d love any input you guys have… I’m using UnityScript.


Not a good idea: Unity do it for you and store assetbundles in a cache location.

use: WWW.LoadFromCacheOrDownload (url, version)

You MUST maintains a bundle version. For instance you add in your ftp a text file with the version number of your assetBundles. When you update an assetbundle and save it on your ftp, then increase your assetbundle version in those text file.

When you use LoadFromCacheOrDownload then you replace version parameter by yours. And unity will donwload it if version is greater than the last downloaded.

In this way you do not have to deal with copy in a particular folder.

Look at this unity doc: http://docs.unity3d.com/Manual/keepingtrackofloadedassetbundles.html

You will find a AssetBundleManager sample code. I use it.

See: Unity - Manual: Preparing your application for In-App Purchases (IAP)

This is an iOS documentation page, but the same approach should work for other mobile devices.

You can use System.IO.File.WriteAllBytes()

using System.IO;
public string url = "myweb.com/myAsset";
public string saveTo = "/folder/myAsset";
public bool alreadyDownloaded = false;
IEnumerator SaveAndDownload(){
WWW www = new WWW(url)
yield return www;
byte[] bytes = www.bytes;

and you’re ready

And what’s about a dlc ? If the user cleans the cache or if the cache is too small to store the asset bundle ? If the user doesn’t know how to cleans the cache ?

I’m looking for the same idea : put my assetbundle on a webserver and then my application can download it and copy inside the internal memory of my device.

Well I put my code here, it works perfectly on my pc but on Android I always got the same and boring error “Asset Bundle header is too small”. Indeed the file is created internally but it isn’t filled with the data.

I’ve been looking for many problems and solutions :

  • Version of Android : Kitkat 4.4 prohibits writing, so I have upgraded my version
  • Assetbundle which is compressed while AssetBundle.CreateFromFile needs an uncompressed assetbundle, so I have made an uncompressed bundle
  • Assetbundle is different according to platforms, so I have made an assetbundle for Android (+uncompressed as well)
  • And now I’m looking for C# managed array (byte array here) can’t be interpreted by Android ?

Here is the code :

public GameObject cible;
	public Scrollbar progressbar;
	public Text displayedtext;
	public GameObject progress;

	static WWW objSERVER;
	static string pathURL;
	static string pathLOCAL;

	//IEnumerator allows yield so the information is not accessed
	//before it finished downloading
	IEnumerator Start () 
		pathURL = "www.mywebsite.net/file"; //location of the file on the server
		pathLOCAL = Application.persistentDataPath + "/../assetbundles/"+"test" +".unity3d"; //location of the file on the device

		objSERVER = new WWW(pathURL);

		// Wait for download to finish
		yield return objSERVER;

		// Save it to disk
		Debug.Log ("------------------- HERE THE PATH -------------------" + "

" + Application.persistentDataPath);
AssetBundle objLOCAL = AssetBundle.CreateFromFile (pathLOCAL);
yield return objLOCAL;

		// Instantiate the asset bundle
		GameObject Model3D = Instantiate (objLOCAL.mainAsset) as GameObject;

		// Parenting
		Model3D.transform.parent = cible.transform;

		// Positioning
		Model3D.transform.localPosition = new Vector3 (0.62f, -0.98f, 0.94f);

		// Resize it
		Model3D.transform.localScale = new Vector3 (0.10f, 0.10f, 0.10f);

		objLOCAL.Unload (false);

	public void SaveDownloadedAsset(WWW objSERVER) 
		// Create the directory if it doesn't already exist
		if (!Directory.Exists(Application.persistentDataPath + "/../assetbundles/"))
			Directory.CreateDirectory(Application.persistentDataPath + "/../assetbundles/");

		// Initialize the byte string
		byte[] bytes = objSERVER.bytes;

		// Creates a new file, writes the specified byte array to the file, and then closes the file. 
		// If the target file already exists, it is overwritten.
		File.WriteAllBytes(pathLOCAL, bytes);