Asset Bundle Fails To Load

So I’ve got a problem and can’t work out what I’m doing wrong. I’m creating some scene asset bundles and some resource asset bundles and then trying to load them.

The file downloads and the WWW has valid bytes in it - but calling .assetBundle - in the Editor - throws an error about not being able to load the asset bundle.

  • I’ve made sure that my file names have no spaces
  • I’ve called my files .unity3d
  • The BuildAssetBundle command for the normal resource assets returns true
  • I can download the file using a browser
  • The WWW appears to have downloaded the right number of bytes

My code to create the bundles:

public void BuildBundles()
{
	var builder = new StringBuilder();
	var totalSteps = ((buildScenes ? scenes.Length : 0) + (buildResources ? bundles.Length : 0)) * 2 + 1;
	var step = 0;
	if(buildScenes)
	{
		foreach(var bundle in scenes)
		{
			var client = new WebClient();
			client.Credentials = new NetworkCredential(userName, password);
			var filename = WWW.EscapeURL( bundle.name + "_scene_bundle.unity3d");
			if(EditorUtility.DisplayCancelableProgressBar("Create Bundles " + name, "Creating scene bundle: " + filename,(float)step++/(float)totalSteps))
			{
				EditorUtility.ClearProgressBar();
				return;
			}
			BuildPipeline.BuildStreamedSceneAssetBundle(new [] {AssetDatabase.GetAssetPath(bundle)}, filename, targetForBundle);
			if(EditorUtility.DisplayCancelableProgressBar("Create Bundles " + name, 
				"Uploading scene bundle to " + serverAddressForUpload + "/" + filename,
				(float)step++/(float)totalSteps))
			{
				EditorUtility.ClearProgressBar();
				return;
			}
			client.UploadFile(serverAddressForUpload + "/" + filename, filename);
			builder.AppendLine("scene|" + filename +"|" + DateTime.Now + "|" + version);
		}
	}
	if(buildResources)
	{
		foreach(var bundle in bundles)
		{
			var client = new WebClient();
			client.Credentials = new NetworkCredential(userName, password);
			var filename = WWW.EscapeURL(bundle.typeOfAsset + "_bundle.unity3d");
			if(EditorUtility.DisplayCancelableProgressBar("Create Bundles " + name, "Creating bundle: " + filename,(float)step++/(float)totalSteps))
			{
				EditorUtility.ClearProgressBar();
				return;
			}
			Debug.Log(BuildPipeline.BuildAssetBundle(bundle.assets[0], bundle.assets, filename, BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets, targetForBundle));
			client.UploadFile(serverAddressForUpload + "/" + filename, filename);
			if(EditorUtility.DisplayCancelableProgressBar("Create Bundles " + name, 
				"Uploading bundle to " + serverAddressForUpload + "/" + filename,
				(float)step++/(float)totalSteps))
			{
				EditorUtility.ClearProgressBar();
				return;
			}
			builder.AppendLine("resource|" + filename +"|" + DateTime.Now + "|" + version);
		}
	}
	if(buildScenes && buildResources)
	{
		var client = new WebClient();
		client.Credentials = new NetworkCredential(userName, password);
		if(EditorUtility.DisplayCancelableProgressBar("Create Bundles " + name, 
			"Uploading manifest to " + serverAddressForUpload + "/" + manifestName,
			(float)step++/(float)totalSteps))
		{
			EditorUtility.ClearProgressBar();
			return;
		}

		client.UploadString(serverAddressForUpload  + "/" + manifestName, builder.ToString());
	}
	version++;
	EditorUtility.DisplayProgressBar("Create Bundles", "Finished", 1);
	EditorUtility.ClearProgressBar();
	EditorApplication.SaveAssets();
}

My code to load the bundles:

IEnumerator CheckForBundles()
{
	var client = new WebClient();
	var manifestRequest = new WWW(baseURL + "/" + manifestName);
	Debug.Log("Retrieve Manifest");
	yield return manifestRequest;
	var content = manifestRequest.text;
	var bundles = manifestRequest.text
		.Split('

‘)
.Where(s=>s.Length>10)
.Select(l=>l.Split(’|'))
.GroupBy(a=>a[0], a=>{
return new Bundle { version = int.Parse(a[3]), name = a[1].Replace(" “,”%20"), date = DateTime.Parse(a[2])};
}).ToList();
Debug.Log("Manifest: " + bundles.Count);
//bundles.Reverse();
foreach(var bundleGroup in bundles)
{
foreach(var bundle in bundleGroup)
{

			if(loadedBundles.ContainsKey(bundle.name))
			{
				if(bundle.date <= loadedBundles[bundle.name].date)
					continue;
				bundle.bundle.Unload(true);
				
			}
			Debug.Log("Loading bundle: " + bundle.name);
#if UNITY_EDITOR
			var bundleRequest = new WWW(baseURL + "/" + bundle.name);
#else
			var bundleRequest = WWW.LoadFromCacheOrDownload(baseURL + "/" + bundle.name,bundle.version);
#endif
			yield return bundleRequest;
			if(string.IsNullOrEmpty(bundleRequest.error))
			{
				Debug.Log("Loading bundle: " + bundle.name + " SUCCEEDED");
				if(bundleGroup.Key == "scene")
				{
					bundle.bundle = bundleRequest.assetBundle;
				}
				else
				{
					bundle.bundle = bundleRequest.assetBundle;
					if(bundle.bundle == null)
					{
						continue;
					}
					bundle.assets = bundle.bundle.LoadAll();
					bundle.bundle.Unload(false);
				}
				loadedBundles[bundle.name] = bundle;
			}
			else
			{
				Debug.Log("Loading bundle: " + bundle.name + " FAILED " + bundleRequest.error);

			}
		}
	}
	Debug.Log("Bundle Loading Complete");
	
}

Cross posted on the forum: http://forum.unity3d.com/threads/178414-Asset-Bundle-Fails-To-Load?p=1220210#post1220210

Asset bundles are normally given .assetbundle extensions. Obviously the extension shouldn't matter. Perhaps by calling them .unity3d files, your server is picking a MIME type that appropriate for unity3d files, and this is throwing off the asset bundle loading code? I'd imagine that asset bundles just need to be served as binary data, whereas unity3d files are usually application/vnd.unity.

Right - ok, so I thought I'd read that it had to be .unity3d in a couple of forum threads - that now makes some sense (I have got them working on the local file system now so they are building properly). I'll give it a go.

Well I reckon you are on to something with that - but it isn't down to the .unity3d file extension as both .assetbundle and .bytes also fail. Time to play with my web server settings.

Wireshark or Fiddler will also help you see if anything seems malformed in the request payload.

A very good point.

1 Answer

1

Ok so my problem was the damn upload - I was using WebClient.UploadFile (as per the question) but that apparently decided to append file data and information to the actual file that was on the site :S I’m not sure why. Anyway, I switched to uploading a byte rather than the file and it works fine.