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.

Thanks!

4 Answers

4

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.

hi, the link is no longer available. and it seems that I can't even load my assetbundles using the recommended WWW.LoadFromCacheOrDownload (url, version). using UnityWebRequest, I'm able to load the bundles and was able to check if it is cached by using CAching.IsVersionCached, however, I have no idea where to retreived this 'cached' version of the bundle....seriously... I am running around in circles... seems like the only solution i have right now is to save it to local...which is not recommended.

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.

Thanks for the link, don't know how I missed that!

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;
File.WriteAllBytes(saveTo,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
		SaveDownloadedAsset(objSERVER); 
		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);
	}
}

Yes I am using Unity 5.x. But seems to be same process (more easy on 5) What contains Selection ? Do you set your editor plateforme to Android? As this you can test Android assetBundles in Editor.

Can't use Unity 5.x because it's not compatible with Vuforia My editor plateform is set to Android and Selection contains the active object on which I click on the editor to package it

What error have you got on Android? Can you launch eclipse to retrieve logcat. (or command line)

Well it seems to don't initialize the download because I got "You are trying to load data from a www stream which had the following error when downloading java.net.MalformedURLException : Protocol not found : www.mywebsite.net/file"

OMG OMG OMG FIXED IT ! Hell yes ! Thank you so much, I just forgot the "http://" before my url !! 3 weeks for this..