Monday, February 13, 2012

Unity, AssetBundles, C# and Co-routines

I spent a day figuring out how to do the asynchronous load of an asset bundle in C#. Below is a minimal workign example along with some explanation:

using UnityEngine;

using System.Collections;


public class AssetLoader : MonoBehaviour {

string assetURL="http://localhost/UnityAssets/WorldWizards/TileSets/Tileset_tin01.unity3d";

// Use this for initialization

void Start () {

Debug.Log("Start");

// This is a Unity method that hijaks the .NET co-iterator functionality and

// uses it to create a psuedo co-routine

StartCoroutine(LoadAsset(assetURL));

}

//This is a co-routine method. Co-routines must return the IEnumerator interface

//This is because .NET doesnt really have co-routines, it has a co-iterator. Unity

//cleverly hijacks that to create a co-routine. If you need more information, you

//can try reading the micrsoft docs on yield return, but they are hairy

IEnumerator LoadAsset(string url){

// This call utilizes unity's asset cache to avoid reloading the same assets over again

// If you dont want asset cahchign replace it with:

//WWW www = new WWW(url);

WWW www = WWW.LoadFromCacheOrDownload(url,1);

// This is how you return from the co-routine. The www needs to be passed

// back as a parameter. The .NET mechanism hides this within a synthetically produced

// IEnumerator as its first entry in the enumeration but thats hidden inside of

// StartCoroutine and you'll never see it.

// Whatever is returned must inherit from the base class YieldInstruction

yield return www;

//THis code is run after the www has fetched its data or errorored out

if (www.error!=null){

Debug.LogError(www.error);

Debug.Log (url);

} else {

Debug.Log ("Done");

AssetBundle ab = www.assetBundle;

Object[] tilePrefabs = ab.LoadAll(typeof(GameObject));

foreach(Object obj in tilePrefabs){

Debug.Log (obj.name);

}

}

}

}




Unity's co-routine mechanism is interesting. theoretically you should be able to use it to do just about any kind of co-routine coding. The hitch is that they have hidden the details of YieldInstruction. This goes along with a general semi-crippling philosophy in Unity that they only want you to use the tools they give you the way they already thought they would be used.

Its too bad, because there is a lot of power in the Unity codebase that is completely blocked off from use by the developer.