AssetBundleに含めたアセットやシリアライズしたデータ一覧を確認出来る機能を作ってみました。
AssetBundleに自動で含まれるアセット
AssetBundleは、AssetBundle NameやAddressを設定したアセットが参照するアセット…例えばキャラクターにおけるAnimationやMaterialにおけるTexturerを自動的に含みます。これにより開発者側はPrefabを展開する上で必要なアセット群を全て把握する必要なく、Prefabが使えます。
ただし、意図通りではないアセットも含まれる可能性があり、それがAssetBundleの利用面で色々と問題を起こしやすい部分でもあります。
AssetBundle.LoadAsset(...)
や Manifest に記載されているアセットは、コンテナとして登録されているアセットで、こういった暗黙的に参照され含まれるAssetBundleを確認出来ません。
AssetBundleに含まれるアセットを全て確認する
コンテンツの中身を全て確認します。
下のコードをEditorフォルダ以下に格納した後、 AssetBundleを右クリック→AB/Content Checker
でABの中身を確認出来ます。
テクスチャの中身等やモデル等も確認が可能です。
using System.Collections.Generic; using UnityEditor; using System.Linq; using UnityEngine; public class Checker : EditorWindow { List<Object> allObjects = new List<Object>(); Vector2 pos; private void OnGUI() { using (var scroll = new EditorGUILayout.ScrollViewScope(pos)) { pos = scroll.scrollPosition; foreach (var obj in allObjects) { EditorGUILayout.ObjectField(obj, obj.GetType(), false); } } } [MenuItem("Assets/AB/Content Checker")] static void Open() { var window = CreateInstance<Checker>(); window.ReadContent(); window.Show(); } void ReadContent() { AssetBundle bundle = null; try { bundle = AssetBundle.LoadFromFile(Application.dataPath + AssetDatabase.GetAssetPath(Selection.activeObject).Remove(0, 6)); if (bundle != null) { SerializedObject so = new SerializedObject(bundle); foreach (SerializedProperty content in so.FindProperty("m_PreloadTable")) { allObjects.Add(content.objectReferenceValue); } allObjects = allObjects .Where(c => c != null) .Where(c => c is Component == false ) .Where(c => c is GameObject == false) .Distinct().OrderBy(c => c.name).ToList(); bundle.Unload(false); } else { Debug.LogWarning("this is not assetbundle?"); Close(); } } finally { if( bundle != null) bundle.Unload(false); } } }
例
例えば下のように、アドレスとしてはPrefabとAnimatorControllerのみを設定しています。
これをチェッカーで見ると、Prefabが暗黙的に参照している内で、同じAssetBundleに格納されている全てのアセットを確認出来ます。
またSprite Atlasでの動き等もココで確認しやすいです。下の画像を見ると、Sprite AtlasとAssetBundleを組み合わせる場合、SpriteAtlasに登録したAssetBundleを全て同じAssetBundleに登録している場合、含まれるアセットはパック済みTextureのみである事が確認出来ます。
現状の問題
シェーダーが上手く取れません。
他のAssetBundleをLoadしていると、開いているAssetBundleに含まれるアセットも表示されるかもしれません。
CSVで出力もついてでに作ってみる
複数のAssetBundleの中身を一気に比較する用でCSV出力もつけてみました。
using System.Collections.Generic; using System.Text; using UnityEditor; using UnityEngine; using System.Linq; public class ExportCSV : MonoBehaviour { [MenuItem("Assets/AB/ExportCSV")] static void Export() { var valuePairs = new Dictionary<string, string>(); StringBuilder builder = new StringBuilder(); foreach (var t in Selection.objects) { AssetBundle bundle = null; try { bundle = AssetBundle.LoadFromFile(Application.dataPath + AssetDatabase.GetAssetPath(t).Remove(0, 6)); if (bundle != null) { builder.Append($"{bundle.name}, "); SerializedObject so = new SerializedObject(bundle); List<Object> objs = new List<Object>(); foreach (SerializedProperty content in so.FindProperty("m_PreloadTable")) { objs.Add(content.objectReferenceValue); } objs = objs .Where(c => c != null) .Where(c => c is Component == false) .Distinct().OrderBy(c => c.name).ToList(); foreach (var obj in objs) { builder.Append($"{obj.name}({obj.GetType()}), "); } builder.AppendLine(); } } finally { if (bundle != null) bundle.Unload(true); } } System.IO.File.WriteAllText("ab content.csv", builder.ToString()); } }
感想
エディター基本機能を少し拡張しましたが、案外悪くないかも? ABに含まれるテクスチャの確認が楽で良いです。
AssetBundleに含まれるコンテンツ一覧を確認する #unitytips pic.twitter.com/7iY8RrOtQz
— 椿 (@tsubaki_t1) 2019年3月26日
それとFBXにAssetBundle Nameを含めることでどんだけ無駄なゴミが増えるのかを確認出来ます。