昨天一位朋友在我这里留言,想让我写点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. oracle数据库如何创建角色并对角色授予权限

    目标: 1.创建角色test1_role, 授予create session 权限 2.创建角色test2_role,授予create procedure, create sequence, crea ...

  2. Zerojudge解题经验交流

    题号:a001: 哈囉 背景知识:输出语句,while not eof 题号:a002: 簡易加法 背景知识:输出语句,while not eof,加法运算 题号:a003: 兩光法師占卜術 背景知识 ...

  3. 相机标定:关于用Levenberg-Marquardt算法在相机标定中应用

    LM算法在相机标定的应用共有三处. (1)单目标定或双目标定中,在内参固定的情况下,计算最佳外参.OpenCV中对应的函数为findExtrinsicCameraParams2. (2)单目标定中,在 ...

  4. OLAT & OLTP

    联机事务处理(OLTP)和联机分析处理(OLAP)的不同,主要通过以下五点区分开来. 用户和系统的面向性: OLTP是面向顾客的,用于事务和查询处理 OLAP是面向市场的,用于数据分析 数据内容: O ...

  5. Spark Streaming源码解读之流数据不断接收全生命周期彻底研究和思考

    本期内容 : 数据接收架构设计模式 数据接收源码彻底研究 一.Spark Streaming数据接收设计模式   Spark Streaming接收数据也相似MVC架构: 1. Mode相当于Rece ...

  6. HTTP 权威指南

    第一章 http概述 1.3.1 媒体类型 - http为每种web传输的数据格式加上MIME类型数据标签(multipurpose internet mail 1.4 事务 一个请求 + 一个响应 ...

  7. 如何实现Qlikview的增量数据加载

    笔者备注: 刚刚接错Qlikview,上网搜集的资料,如何处理增量数据. 1 寻找增量时间戳(1)各种数据库:表的创建时间字段和修改时间字段或者最后的修改时间字段:(2)sql server:可以用找 ...

  8. 【转】提高VR渲染速度的最好方法(经典转载)

    VR的基本渲染方法掌握起来并不难,但是最迫切需要解决的问题是VR的出图速度问题.动则需要数小时的渲染时间真的是很难以接受,我们从三个影响速度的参数结合网上一些高手的教程来分析一下. 一.Irradia ...

  9. CSS子元素居中(父元素宽高已知,子元素未知)

    <style> .container{width:400px; height:400px; position:relative;} .center{position:absolute; l ...

  10. MVC 下拉單數據內容綁定

    #region        /// <summary>授權範圍自建列表</summary>        /// <returns></returns> ...