UnityのAssetBundleことはじめ

　業務上、AssetBundleを管理することになったので一から勉強します。
AssetBundleとはなんぞや？という場合は下記がわかりやすいです。
http://docs-jp.unity3d.com/Documentation/Manual/AssetBundlesIntro.html

# AssetBundleの作成
Assets
├── Editor
   ├── ExportAssetBundles.cs
上記のようなフォルダ構成で下記ファイルしEditor拡張します。


```csharp:ExportAssetBundles.cs
using UnityEngine;
using UnityEditor;

public class ExportAssetBundles {
	[MenuItem("Assets/Building")]
	static void ExportResourceNoTrack () {
		string path = EditorUtility.SaveFilePanel ("Save Resource", "", "Test", "unity3d");

		if (path.Length != 0) {
			BuildPipeline.BuildAssetBundle(
				Selection.activeObject, 
				Selection.objects, path);
		}
	}
}
```

　適当なGameObjectを作成 → Prefab化 → Prefabを右クリック → Building
にて作成します。
作成したものはWebサーバなどダウンロードサーバに適当に配置します。
ここでは"Test.unity3d"というものを作成しローカルのWebサーバのstaticに配置してみました。

#AssetBundleのダウンロード・インスタンス化(キャッシュなし)
## 最小構成
　まずは理解しやすいように最小構成でやってみます。
　下記スクリプトをシーン上の適当なオブジェクトにアタッチして実行すると、上記手順で作成したものが表示されるはずです。

```csharp:UseAssetBundle.cs
using UnityEngine;
using System.Collections;

public class UseAssetBundle : MonoBehaviour {
	IEnumerator Start () {
		WWW www = new WWW("http://localhost:8000/m/static/Test.unity3d");
		yield return www;

		Instantiate(www.assetBundle.mainAsset);
	}
}
```

しかし、上記はエラーが処理が全く入っていないので実用的ではありません。

## エラー対応

```csharp:UseAssetBundle.cs
using UnityEngine;
using System.Collections;
using System;

public class UseAssetBundle : MonoBehaviour {
    IEnumerator Start () {
        WWW www = new WWW("http://localhost:8000/m/static/Test.unity3d");
        yield return www;

		if (www.error != null) {
			throw new Exception("WWW Error: " + www.error);
		}

		AssetBundle bundle = www.assetBundle;

		if (bundle == null){
			throw new Exception("bundle is Null.");
		}

		Instantiate(www.assetBundle.mainAsset);
    }
}
```

自分の環境でエラー原因は下記がありました。

* 通信エラー
WWW Errorのところで
Rejected because no crossdomain.xml policy file was found
となった場合は
http://qiita.com/okuhiiro/items/cdab95604b61cb189ad6
を参照ください。

* ファイルがない
WWW Errorのところで404 NOT FOUND
となった場合は、多分ファイルが存在しない可能性があります。

* ファイルがなんかおかしい
"bundle is Null"となる場合は、ファイルは存在するがなんか形式がおかしいとかでAssetBundleオブジェクト化できなかったりする可能性があります。

##最適化
　usingとbundle.Unloadを追加しました。
いろいろメモリ周りの最適化を図りました。

```csharp:UseAssetBundle.cs
using UnityEngine;
using System.Collections;
using System;

public class UseAssetBundle : MonoBehaviour {
	IEnumerator Start () {
		using(WWW www = new WWW("http://localhost:8000/m/static/Test.unity3d"))
		{
			yield return www;

			if (www.error != null) {
				throw new Exception("WWW Error: " + www.error);
			}

			AssetBundle bundle = www.assetBundle;

			if (bundle == null){
				throw new Exception("bundle is Null.");
			}

			Instantiate(www.assetBundle.mainAsset);

			bundle.Unload(false);
		}
	}	
}
```

#AssetBundleのダウンロード・インスタンス化(キャッシュあり)
　WWW.LoadFromCacheOrDownloadを使うとキャッシュするのでよいらしい。
while(!Caching)〜もあったほうがよいっぽい。

```csharp:UseAssetBundle1.cs
using UnityEngine;
using System.Collections;
using System;

public class UseAssetBundle1 : MonoBehaviour {
	IEnumerator Start (){
		using(WWW www = WWW.LoadFromCacheOrDownload ("http://localhost:8000/m/static/Test.unity3d", 1))
		{
			yield return www;

            while (!Caching.ready) yield return null;

			if (www.error != null) {
				throw new Exception("WWW Error: " + www.error);
			}

			AssetBundle bundle = www.assetBundle;

			if (bundle == null){
				throw new Exception("bundle is Null.");
			}

			Instantiate(www.assetBundle.mainAsset);

			bundle.Unload(false);
		}
	}
}
```