unity5.X AssetBundle使用(二 )

转载 2015年07月07日 22:50:09
昨天一位朋友在我这里留言,想让我写点Unity5的AssetBundle心得。于是我就看了相关的介绍,和自己确切的做了一次。下面来谈谈所谓的心得。
如果你觉得自己对AssetBundle不熟悉,建议先看看另外一篇文章:
http://liweizhaolili.blog.163.com/blog/static/16230744201541410275298/

先来说说关于旧版本的AssetBundle的事情。
之前我写了一个批量导出AssetBundle的小插件,有朋友留言说我没有解决依赖关系。后来在一位同事的指导下,我终于把这个问题搞清楚了,其实说白了过程就是先扫描所有要打包的资源,然后用AssetDatabase.GetDependencies获得所有的依赖,自己记录起来,由于怕资源之间有重名的,所以最好用AssetDatabase.AssetPathToGUID获得资源的唯一id,然后存起来。获得了所有依赖关系之后,再使用BuildPipeline.PushAssetDependencies和BuildPipeline.PopAssetDependencies按照层级和顺序来打包。这样打出来的资源就完全的保留了依赖关系,文件也拆得很散很小,不会重复打包了。
在加载的时候,由于我们是预先记录了各个资源的依赖关系,所以在加载某一个资源的时候,先去保存的文件里面查找它的依赖关系,把所有用到的依赖资源都先加载一次,然后再加载它,就能完整的加载出一个想要的模型之类了。
这就是完整的旧版本AssetBundle依赖打包和加载的流程了。不过由于是受人指导学会的,所以不方便把全部代码贴出来。
再来看看5.0版本的心AssetBundle的使用情况:
看到新版本的AssetBundle,我那位同事估计会一口老血喷在屏幕上面。那是因为,这个辛辛苦苦做出来的打包策略,Unity已经集成了。
新版本的AssetBundle在打包的时候多了一个叫做BuildPipeline.BuildAssetBundles(outputPath)的方法,然后每一个资源可以设置一个assetBundleName。只要你调用这个方法,那么所有已经设置过assetBundleName的资源,就会自动打包,具体的好处有:
1、可以直接在编辑器UI上设置操作
2、提供了更简便的脚本API
3、Unity本身会处理所有的依赖关系
4、生成了一种叫做manifest的文件,用于记录资源之间的依赖关系,并以链式结构记录,修改时只需修改链的其中一环
5、增量打包功能。
以上的好处,是官方说明的,我大概操作了一下,说的都是事实,只是使用时有点需要注意的地方。
很明显的看出,这些优点,正是我那位同事已经做过的事情,和一些暂时没有做到的事情。
先来说说最多人关心的问题,Unity自己处理依赖关系。
实际上来说,所有需要打包成AssetBundle的资源,你是要先赋予它一个assetBundleName的,在它有了assetBundleName之后,实际上它的信息已经存在于AssetDataBase里面了。所以在打包的时候,只需要调用BuildPipeline.BuildAssetBundles方法,它会把记录了的在AssetDataBase里面的所有资源先计算出依赖关系,再拆分打包。这个步骤是一点问题都没有的。要注意的是,你所有依赖的资源都必须赋予assetBundleName,不然,依赖就不会被拆分。
在加载的时候,AssetBundle的特性是和旧版本一样的,就是当一个目标资源的依赖资源已经存在与内存中(也就是已经被加载过了),那么在加载目标资源的时候,Unity会自动的帮你找到依赖关系。所以在加载的时候实际上还是要你手动加载依赖资源的。这一点和旧版本一样。
再来说说打包工具的编写。
虽然官方说得很美好,一句BuildPipeline.BuildAssetBundles(outputPath)就可以直接把所有资源都打包了,而需要打包的资源可以在编辑器界面直接输入。但实际上由于上面说到的必须赋予每一个依赖资源assetBundleName,你不可能每一个资源去手动的查找用到的依赖资源再在编辑器输入名字,所以旧版本的打包流程还是要的。
首先,你可以遍历需要打包的文件夹,把所有需要打包的预设或者资源都找到,然后设置assetBundleName,然后,通过AssetDatabase.GetDependencies方法逐个找到资源的依赖资源路径,用AssetDatabase.AssetPathToGUID算出每个资源的唯一ID,然后将唯一ID当做assetBundleName赋予给每个依赖资源。最后,调用BuildPipeline.BuildAssetBundles(outputPath)打包到指定位置。
最后说说加载。
由于依赖关系都存在于manifest中,所以在加载资源之前,要先加载manifest文件。
实际上在打包的时候,会有一个总的manifest文件,叫做AssetBundle.manifest,然后每一个小的资源分别有一个自己的manifest文件。在我们加载的时候,需要先把总的AssetBundle加载进来。
比如这样:
        string mUrl = Cdn + "AssetBundle";
        WWW mwww = WWW.LoadFromCacheOrDownload(mUrl, 0);
        yield return mwww;
        if (!string.IsNullOrEmpty(mwww.error))
        {
            Debug.Log(mwww.error);
        }
        else
        {
            AssetBundle mab = mwww.assetBundle;
            AssetBundleManifest mainfest = (AssetBundleManifest)mab.LoadAsset("AssetBundleManifest");
            mab.Unload(false);

其中Cdn是我的资源路径,加载完之后,得到了一个AssetBundleManifest 对象。

然后根据我们需要加载的资源名称,获得所有依赖资源:
            string[] dps = mainfest.GetAllDependencies(realName);
            AssetBundle[] abs = new AssetBundle[dps.Length];
            for (int i = 0; i < dps.Length; i++)
            {
                string dUrl = Cdn + dps[i];
                WWW dwww = WWW.LoadFromCacheOrDownload(dUrl, mainfest.GetAssetBundleHash(dps[i]));
                yield return dwww;
                abs[i] = dwww.assetBundle;
            }
其中realName是想加载的AssetBundle的名字,需要带扩展名。

通过了这一步,所有的依赖资源都加载完了,可以加载目标资源了:
 WWW www = WWW.LoadFromCacheOrDownload(url, mainfest.GetAssetBundleHash(realName+".ab"), 0);
            yield return www;
            if (!string.IsNullOrEmpty(www.error))
            {
                Debug.Log(www.error);
            }
            else
            {
                AssetBundle ab = www.assetBundle;
                GameObject gobj = ab.LoadAsset(realName) as GameObject;
                if (gobj != null)
                    Instantiate(gobj);
                ab.Unload(false);
            }
            foreach (AssetBundle ab in abs)
            {
                ab.Unload(false);
            }
到这一步,所有的资源都加载完毕了。注意的是,记得Unload,不然下次就加不进来了。或者不Unload的话,就做一个字典记录所有加载过的AssetBundle,还有它们的引用计数器。那样就可以先判断是否存在在加载。
以上就是Unity5.0的AssetBundle的使用方法了。下面来吐槽一下。
1、看Unite2014大会的视频介绍时,感觉这个东西真好,提供了这么强大的功能和这么简单的API。但实际用过之后,发现整个打包和加载的过程其实和旧版差不多,真正有意义的功能,是manifest的链式结构,和增量打包功能。
2、我在没有使用之前,以为可以按照文件夹结构来打包,那样的话,就可以简单的从Resources.Load和外部WWW加载中做切换,只需要替换一个CDN地址就可以了。但实际上Unity把所有AssetBundle都打包在了同一个目录,在这个转换的过程中,我们还需要记录一下两者的对应关系。
3、资源打包的策略有时候和项目的设计本身有关,如果是阶段性很明确的资源管理,可能旧版的AssetBundle打包也不错。
4、现在只看了Unity5的AssetBundle觉得不错,但又看了一下其他功能,发现Unity5的很多功能都改了,这样的大改动对于旧项目来说有可能是影响非常大的,是不是值得为了新的AssetBundle而升级Unity,还是需要更多的评估。

Unity5的AssetBundle的一点使用心得

昨天一位朋友在我这里留言,想让我写点Unity5的AssetBundle心得。于是我就看了相关的介绍,和自己确切的做了一次。下面来谈谈所谓的心得。 如果你觉得自己对AssetBundle不熟悉,...
  • wuming0108
  • wuming0108
  • 2015年07月31日 18:17
  • 2721

assetbundle 坑爹总结

转自:http://www.cnblogs.com/wonderKK/p/4266680.html 一、关于依赖打包 1、当一个被打包的资源A引用了其他的资源B,并且没有被打成一个包时,要...
  • hyf2713
  • hyf2713
  • 2016年03月15日 15:17
  • 539

Unity5的AssetBundle的一点使用心得

http://liweizhaolili.blog.163.com/blog/static/162307442015282017852/ 昨天一位朋友在我这里留言,想让我写点Unity5的Asse...
  • e295166319
  • e295166319
  • 2016年11月29日 18:34
  • 668

unity5.X AssetBundle使用(一 )

之前曾经写了一篇博客介绍Unity5的AssetBundle,结果似乎很受关注。不过似乎很多人看了之后都不懂,主要是因为不太明白AssetBundle是什么,它的依赖关系和结构是什么的,就直接想拿代码...
  • qq617119142
  • qq617119142
  • 2015年07月07日 22:47
  • 2755

Unity5.X打包与加载AssetBundle

所有脚本代码来自官方打包AssetBundle:在Editor界面,点击prefab或文件,在AssetsBundle处设置此prefab的Assetsbundles属性。 点New可以创建Asse...
  • liu_if_else
  • liu_if_else
  • 2016年10月07日 18:38
  • 2393

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

Unity5.x AssetBundle打包和加载深入分析1.打包unity 可以通过为资源设置assetBundleName的方式打包资源首先我们需要批量为资源设置assetBundleName ...
  • xuzongchao
  • xuzongchao
  • 2017年03月16日 23:21
  • 1531

Unity5.x AssetBundle 的变化

前言:下面文字适用于对AssetBundle有一点了解的朋友,阅读大约10分钟,AssetBundle基本概念等知识可以网上找一下。1、打包API的变化Unity5.x中,AssetBundle相关的...
  • k46023
  • k46023
  • 2017年03月16日 06:40
  • 2455

关于采用Unity 5.x 提供的增量式打包单个模型后AssetBundle doesn’t have main asset解决方法

关于采用Unity 5.x 提供的增量式打包单个模型后AssetBundle doesn’t have main asset解决方法1.可通过AssetBundle.LoadAllAssetsAsyn...
  • yuxisanno139
  • yuxisanno139
  • 2016年10月27日 15:52
  • 523

unity5.x assetbundle打包和加载

打包 AssetBundleBuild[] abs = new AssetBundleBuild[1]; abs[0].assetNames = new string[]{"Assets/RawAs...
  • linxinfa
  • linxinfa
  • 2017年02月04日 21:02
  • 857

unity5.X AssetBundle

虽然官方说得很美好,一句BuildPipeline.BuildAssetBundles(outputPath)就可以直接把所有资源都打包了,而需要打包的资源可以在编辑器界面直接输入。但实际上由于上面说...
  • Momo_Da
  • Momo_Da
  • 2017年02月28日 11:51
  • 230
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:unity5.X AssetBundle使用(二 )
举报原因:
原因补充:

(最多只允许输入30个字)