Unity5.x AssetBundle打包和加载深入分析
1.打包
unity 可以通过为资源设置assetBundleName的方式打包资源首先我们需要批量为资源设置assetBundleName
上代码:
public static void ReName()
{
Object[] objs = Selection.objects;
for (int i = 0; i < objs.Length; i++)
{
string path = AssetDatabase.GetAssetPath(objs[i]);
FileInfo dir = new FileInfo(path);
string parent = dir.Directory.Name;
AssetImporter.GetAtPath(path).assetBundleName = parent + "/" + objs[i].name;
if (i % 10 == 0)
{
bool isCancel = EditorUtility.DisplayCancelableProgressBar("修改中", path, (float)i / objs.Length);
if (isCancel)
{
EditorUtility.ClearProgressBar();
break;
}
}
}
EditorUtility.ClearProgressBar();
}
其中
AssetImporter.GetAtPath(path).assetBundleName="name"
就是为资源设置assetBundleName
可以以路径的形式命名,打包时会自动打包到相应的路径下,比如:
AssetImporter.GetAtPath(path).assetBundleName="aaa/bb/name"
资源命名好了之后,下面就开始打包了
打包代码只需要一句
BuildPipeline.BuildAssetBundles("Assets/AssetBundles", BuildAssetBundleOptions.None, BuildTarget.Android);
便可将资源打包到相应目录和对应的平台。
下面是我的测试
这里我将两个sprite打包
可以看到这里已经将AssetBundle 打包到了AssetBundles的Sprite文件夹下。到这里打包的过程就算结束了
加载
打包完成后剩下的自然就是加载
我们先将刚才打包的两个Sprite加载出来:
Object[] sprites = bundle2.LoadAssetWithSubAssets(bundle.GetAllAssetNames()[0], typeof(GameObject));
GameObject sprite = GameObject.Instantiate(sprites[0]) as GameObject;
AssetBundle bundle1 = AssetBundle.LoadFromFile("Assets/AssetBundles/sprites/sprite-00010");
Object[] sprites1 = bundle2.LoadAssetWithSubAssets(bundle1.GetAllAssetNames()[0], typeof(GameObject));
GameObject sprite1 = GameObject.Instantiate(sprites1[0]) as GameObject;
通过这段代码将资源加载到内存中
运行后同过Pfofiler查看,发现内存中存在两份Sprite-00010的贴图
这是因为两个Sprite都引用了同一份贴图
导致贴图打包重复
解决这个问题的思路有两个
1.将有同样贴图的资源打包到一个AssetBundle里
2.为被引用的贴图设置AssetBundleName,这样打包时会将贴图也打包成AssetBundle并自动处理引用
这里我们测试第二种
将贴图打包后我们查看之前Sprite的AssetBundle的信息发现Unity已经自动处理了引用关系:
Dependencies就是引用的AssetBundle
所以我们要将其引用的资源也加载进来
完整代码如下:
AssetBundle bundle0 = AssetBundle.LoadFromFile("Assets/AssetBundles/textures/sprite-00010");
AssetBundle bundle = AssetBundle.LoadFromFile("Assets/AssetBundles/sprites/sprite-00010");
Object[] sprites = bundle.LoadAssetWithSubAssets(bundle.GetAllAssetNames()[0], typeof(GameObject));
GameObject sprite = GameObject.Instantiate(sprites[0]) as GameObject;
AssetBundle bundle1 = AssetBundle.LoadFromFile("Assets/AssetBundles/sprites/sprite-00011");
Object[] sprites1 = bundle1.LoadAssetWithSubAssets(bundle1.GetAllAssetNames()[0], typeof(GameObject));
GameObject sprite1 = GameObject.Instantiate(sprites1[0]) as GameObject;
bundle0.Unload(false);
bundle1.Unload(false);
bundle.Unload(false);
再次测试可以看到内存中Sprite-00010的贴图只剩一份了
但是加载时难道所有的引用都要手动一个个加载吗
这里打包后都会有一个AssetBundles
其中manifest文件中存储了所有AssetBundle的依赖信息
同过下面代码就能获取指定资源的所有依赖资源了
AssetBundle ab = AssetBundle.LoadFromFile("Assets/AssetBundles/AssetBundles");
AssetBundleManifest abm = ab.LoadAsset("AssetBundleManifest") as AssetBundleManifest;
string[] ss = abm.GetAllDependencies("sprites/sprite-00010");
然后就可以遍历加载了。很简单吧
- 上一篇: c# Bitmap byte[]互转
- 下一篇: 巧妙突破大容量邮箱附件大小限制