牛骨文教育服务平台(让学习变的简单)
博文笔记

Unity5.x AssetBundle打包和加载深入分析

创建时间:2017-03-16 投稿人: 浏览次数:2040

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");

然后就可以遍历加载了。很简单吧

声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。