昨天一位朋友在我这里留言,想让我写点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都打包在了同一个目录,在这个转换的过程中,我们还需要记录一下两者的对应关系。(其实这一点是错误的,assetName只要是带“/”的,就能自动生成文件夹结构的,之后的文章都忘记提了,误导了大家)
3、资源打包的策略有时候和项目的设计本身有关,如果是阶段性很明确的资源管理,可能旧版的AssetBundle打包也不错。
4、现在只看了Unity5的AssetBundle觉得不错,但又看了一下其他功能,发现Unity5的很多功能都改了,这样的大改动对于旧项目来说有可能是影响非常大的,是不是值得为了新的AssetBundle而升级Unity,还是需要更多的评估。
 

Unity5的AssetBundle的一点使用心得的更多相关文章

  1. 再详细的介绍一下Unity5的AssetBundle

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

  2. 谈谈我用Unity5的AssetBundle踩到的几个坑

    在上段时间摸索了Unity5的assetbundle用法之后,我在项目里面全面的使用起来,于是发现了一些坑,这里和大家分享一下,顺便说说我是怎样解决的. 首先是图集打包的问题.这个问题在unity5. ...

  3. BUI Webapp用于项目中的一点小心得

    接触BUI也有一段时间,也用在了移动端的项目开发中,总的来说,该框架用起来也挺灵活的,控件可以自由定制,前提是自己能认真地学习该框架的api,因为api里面说的东西比较详细,如果没有仔细看的,可能有些 ...

  4. [Unity] unity5.3 assetbundle打包及加载

    Unity5.3更新了assetbundle的打包和加载api,下面简单介绍使用方法及示例代码. 在Unity中选中一个prefab查看Inspector窗口,有两个位置可以进行assetbundle ...

  5. Backbone的一点使用心得

    Backbone的其实感觉上上手很难,大概在一年前就想实践下,结果总是没有付诸行动,这次需求中狠狠心决定一定要使用一次看看,感受下. 可是第一步真的比较困难,因为直接看API好像没有感觉就在网上找实例 ...

  6. ASP.NET MVC Autofac依赖注入的一点小心得(包含特性注入)

    前言 IOC的重要性 大家都清楚..便利也都知道..新的ASP.NET Core也大量使用了这种手法.. 一直憋着没写ASP.NET Core的文章..还是怕误导大家.. 今天这篇也不是讲Core的 ...

  7. python+tesseract验证码识别的一点小心得

    由于公司需要,最近开始学习验证码的识别 我选用的是tesseract-ocr进行识别,据说以前是惠普公司开发的排名前三的,现在开源了.到目前为止已经出到3.0.2了 当然了,前期我们还是需要对验证码进 ...

  8. Qt使用com组件的一点小心得(使用Qt自带的工具dumpcpp生成.h和.cpp文件)

    这几天工作中要用到Qt调用com组件,主要用到的类型有dll和ocx,使用他们的方法很简单:1.将com组件注册到系统中.2.使用Qt自带的工具dumpcpp将com组件生成cpp和头文件.3.然后就 ...

  9. 新手学分布式 - Envoy Proxy XDS Server动态配置的一点使用心得

    Envoy Proxy 动态API的使用总结 Envoy Proxy和其它L4/L7反向搭理工具最大的区别就是原生支持动态配置. 首先来看一下Envoy的大致架构 从上图可以简单理解:Listener ...

随机推荐

  1. nodejs初探(一)环境搭建,开发工具安装

    简介 JavaScript是一种运行在浏览器的脚本,它简单,轻巧,易于编辑,这种脚本通常用于浏览器的前端编程,但是一位开发者Ryan有一天发现这种前端式的脚本语言可以运行在服务器上的时候,一场席卷全球 ...

  2. QT学习之路--菜单、工具条、状态栏

    下面一些是 Menu Bar,用于显示菜单;再下面一点事 Toolbar areas,用于显示工具条,Status Bar,就是状态栏. Qt 提供了一个 QStatusBar 类来实现状态栏. Qt ...

  3. CRM 权限与分派不一样问题

    问题描述: 1 userA用户 为 区域经理; 2  区域经理(角色) 为 分派给userA的安全角色; 3  区域经理(角色) 设置了对实体 客户 的读权限为 业务部门级; 按正常来说userA 应 ...

  4. 执行powershell脚本

    打开powershell运行窗口: powershell.exe C:\Users\Administrator\Desktop\a.ps1 -a $a. -a $a :  vbs脚本路径(如 C:\h ...

  5. MySQL_杭州11月销售昨日未上架的SKU_20161212

    #C034杭州11月销售昨日未上架的SKU SELECT 城市,a.订单日期,a.客户数,a.订单数,b.产品数,a.金额,c.销售确认额,c.毛利额,c.毛利率 FROM ( SELECT 城市,订 ...

  6. codeforces 361 B - Mike and Shortcuts

    原题: Description Recently, Mike was very busy with studying for exams and contests. Now he is going t ...

  7. CRC

    #define POLY 0x1021 /** * Calculating CRC-16 in 'C' * @para addr, start of data * @para num, length ...

  8. java-web乱码问题解决

    <一>乱码问题(设置tomcat uriencoding=’utf-8’); 统一设置编码过滤器 <1>get请求: request.setCharacterEncoding( ...

  9. Jquery Mobile 动态添加元素然后刷新 转

    Jquery Mobile 动态添加元素然后刷新 (2013-05-09 12:39:05) 转载▼ 标签: it 分类: Mobile jquery 表单元素每一个元素都有自己刷新的方法,每当改变它 ...

  10. Jquery 生成时钟

    $(function(){ showTime(); }): function showTime () { var curtime=new Date(); $(".getDateTime&qu ...