再详细的介绍一下Unity5的AssetBundle

之前曾经写了一篇博客介绍Unity5的AssetBundle,结果似乎很受关注。不过似乎很多人看了之后都不懂,主要是因为不太明白AssetBundle是什么,它的依赖关系和结构是什么的,就直接想拿代码去用,而导致了很多人说看不懂啊,说什么有错误啊,诸如此类。我想了一下,还是应该从最基础的东西说起,不厌其烦的说,才会省去大家加我QQ问问题了,毕竟平时上班忙,看到一些人把我当翻译词典查,我肯定会态度不好的。

一、什么是AssetBundle

估计很多人只知道Unity的模型之类的东西可以导出成一种叫做AssetBundle的文件,然后打包后可以在Unity程序运行的时候再加载回来用。

那么AssetBundle是一个什么样的东西呢?其实AssetBundle只是一种使用LZMA压缩方式压缩的资源文件。具体LZMA是什么请百度,你可以理解成就是一种压缩文件就行了,至于它的后缀名是什么,一点关系都没有,你可以自己定。

AssetBundle打包的时候,你可以指定一个mainAsset,那么加载完之后就可以通过AssetBundle.mainAsset来获取到了。你也可以不指定mainAsset,直接打包一堆内容进去,然后加载后通过AssetBundle.LoadAsset指定名字的读取出来。

在资源之间,存在着依赖的关系。你可以把资源拆分得很细,比如一个模型,由网格模型、材质、贴图构成,你可以把每一个小部分都拆开,各自打包成压缩文件。当Unity需要加载使用的时候,把该模型的所有依赖的小资源都加载起来,然后根据依赖关系组装,就变回了我们看到的资源了。

二、AssetBundle的依赖结构

要说明依赖关系结构,我们还是使用上面的例子,一个模型,分为了网格模型、材质、贴图。那么他们是怎样依赖的呢?然后在Unity5的打包里面,他们是怎样表现出依赖关系的呢?

接下来做一个小小的实验:

我准备了4张贴图,分别叫做t1、t2、t3、t4,然后建立了两个材质球,分别是m1、m2,m1材质使用了t1、t2、t3三张贴图,m2材质使用了t4贴图。

最后建立两个模型,我就使用unity内置的模型了。obj1是一个cube,obj2是一个quad。obj1使用了m1材质,obj2使用了m2材质。然后obj1和obj2都做成了预设,放在了Assets/Resources/Obj/下面

那么现在他们的结构应该是这样的:

接下来,先只设置obj1的assetBundleName,然后导出

导出之后,我们看看AssetBundle.manifest

里面只有一个Info,就是刚才我们命名的obj1.ab,而obj1.ab下面的Dependencies是空的,也就是它没有任何依赖了。

再看看obj1.ab.manifest

它里面包含了类型的哈希码、Assets资源的路径,和依赖。这里它的依赖还是空的。

接下来把obj2也赋予AssetBundleName:

再导出,会发现除了刚才的文件以外,会多了2个文件,就是obj2.ab和obj2.ab.manifest。

还是打开AssetBundle.manifest看看,会发现

这次的Info变成了2个,分别是obj1.ab和obj2.ab

打开obj1.ab.manifest
 

发现和刚才没什么变化。

再看看obj2.ab.manifest
  

它的结构和obj1.ab.manifest差不多。

刚才只是把2个模型设置了导出AssetBundle,接下来我会把两个材质和四张贴图都设置导出

不厌其烦的把图贴上来:

这时候导出,我们的所有依赖关系都应该存在了。导出之后,多了很多文件,是这样的:

再来看AssetBundle.manifest

这次看到的Info有7个了,其实我们设置了多少个AssetBundleName导出,它就应该有多少个Info。

看obj1.ab.manifest

这次看到它的Dependencies,会看到有依赖了,写的是一个本地的地址。有人会说,这个绝对路径有问题啊,我把这个文件放到cdn上面,路径就会不对啊。这个先不急,下面会说明是什么回事。

看m1.ab.manifest

会发现结构差不多,但依赖列表里面会有三个地址,就是我们三张贴图的地址了。

看obj2.ab.manifest 和 m2.ab.manifest情况会差不多

接下来,要做最后一步试验了,比如刚才我已经是整个项目的导出了,现在我突然需要改动其中的一个小部分,现在我就把t4不导出了。

那么现在我们再整个项目的AssetBundle导出,会怎样?

导出完之后,看目录,会发现文件和刚才是一样多的,t4.ab并没有被删掉。

再看AssetBundle.manifest
 

Info变成6个了,而里面某些项的依赖列表变了

看obj1.ab.manifest

和刚才没有变化

看obj2.ab.manifest

和刚才也是没有变化的

看m2.ab.manifest

这里的依赖列表没有了。

这其实就是AssetBundle的链式结构和增量打包了。一个小的部分改变了,它将会改变的地方只有总的AssetBundle.manifest,还有直接依赖于它本身的manifest。其他不依赖的部分是不需要重新打包的。

还有一点需要注意的地方是,除了manifest文件以外,还有一个没有后缀名称的AssetBundle文件。这个文件其实才是包含了所有的依赖关系的总的依赖关系配置文件,刚才我们能用txt打开的manifest文件,都只是用来做本地依赖关系和增量打包的时候用的。我们加载AssetBundle的时候,完全不需要加载那些manifest文件的,只需要那个没有后缀名称的AssetBundle文件(具体名字和你导出的文件夹有关)就行了,它代表的是该项目的所有AssetBundle的依赖关系。

所以,刚才我们看到manifest里面用的都是本地的绝对路径,那是针对你本地打包时用的,和加载无关。

三、导出AssetBundle和自动设置名称

刚才我们都是直接的输入AssetBundleName来导出AssetBundle的,其实这一步可以使用代码自动完成

在Unity项目内部,每一个小的资源(网格、材质、贴图、声音等),都会有一个唯一的哈希Id的,是一串很长的字母和数字组合。我们可以通过AssetDatabase.AssetPathToGUID来获得这个ID。

那么自动设置就变得简单了,可以通过以下的代码,我们可以设置一个总的prefab的AssetBundleName,然后自动获得它身上的所有依赖,然后获得每个依赖资源的唯一Id,再赋予AssetBundleName就行了

四、加载AssetBundle的步骤

通过上面导出AssetBundle的说明,估计现在想要把它加载起来就变得简单了。

首先需要明白一个规则,资源的依赖关系组装是unity本身会自动完成的。比如一个资源A,它是依赖于资源B和资源C的,那么如果我们需要加载资源A进来并正确的显示出来,我们必须先把资源B和资源C加载,然后再加载资源A。当资源A加载进来之后,发现内存里面已经有资源B和资源C了,它会自动的组装起来。

那么再看看加载的步骤了:

1、获得总的依赖配置

刚才已经说明了,真的有用的依赖配置文件是没有后缀名称的AssetBundle文件,所以我们需要加载的就是这个文件了。

string mUrl = Cdn + "AssetBundle";

然后www加载。

之后很多人看不懂,说我这个Cdn是什么东西,“AssetBundle”又是什么东西,现在应该明白了吧?Cdn就是你的资源服务器路径,“AssetBundle”就是文件名,它没有后缀,具体的名字是和你导出的文件夹一样的。

加载后,通过AssetBundle.LoadAsset("AssetBundleManifest"),就可以把刚才那个没有后缀名的文件转成AssetBundleManifest对象mainfest。

2、根据名称找到目标加载资源的所有依赖

获得了AssetBundleManifest对象mainfest之后,比如我们实际上是需要加载obj1.ab的,这在刚才的AssetBundle.manifest里面可以知道,它的Info里面就有obj1.ab。然后我们通过

string[] dps = mainfest.GetAllDependencies("obj1.ab");

就可以获取到obj1.ab的所有依赖了,包括了子依赖,比如它依赖于m1.ab,然后m1.ab依赖于t1.ab、t2.ab、t3.ab,那么这里获取到的就应该是4个依赖了。分别是m1.ab、t1.ab、t2.ab、t3.ab。

3、加载所有依赖的资源

获取到obj1.ab的所有依赖之后,就应该逐个的去加载他们了。分别www加载他们,然后保存他们的AssetBundle。

4、加载目标加载资源

当加载了所有的依赖资源之后,就可以光明正大 的去加载目标资源了,这里我们的目标资源就是obj1.ab。

5、实例化显示

obj1.ab加载完之后,你爱怎样用都可以,直接实例化出来吧。

由于AssetBundle是不能重复加载的,如果你需要多次加载一个资源,你有2个选择,要么加载了就Unload(false)卸载了它。要么你可以把它存起来,当需要相同名字的AssetBundle的时候,直接取出来。

五、最后的建议

1、Unity5的新版AssetBundle好像是一套全新的系统,其实和旧系统的差别并没有很大,只是自动生成了依赖配置文件而已。这一个步骤实际上完全可以自己实现的,那些配置文件可以用自己喜欢的格式生成,然后加载的时候再自己想办法把依赖关系找回来就行了。

2、个人觉得把AssetBundle拆得太碎并不是一件好事情。为什么这么说呢?用过电脑的人都知道,拷贝文件的时候是一个个碎的文件拷贝快?还是把一堆文件压缩成一个包,然后拷贝快?如果加载一个模型,需要分别加载十几次依赖资源,才能显示,这个过程中发送这么多的www或者http请求,过程有点危险。至于说冗余文件的问题,自己考虑一下分布策略吧。

2、 一般来说,这种东西都需要配合着一套资源管理的系统来用的,所以在上一篇博客里面,我只是介绍新AssetBundle的特性,不太可能整一套系统都搬出来,只写了几句有代表性的关键方法当做伪代码来说明。结果很多人要么就说乱,要么就说有错误。其实说来说去,就是自己没搞懂原理,又急着拿别人的代码来用……做人还是踏实一点的好。

时间: 2024-09-29 09:30:38

再详细的介绍一下Unity5的AssetBundle的相关文章

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

在上段时间摸索了Unity5的assetbundle用法之后,我在项目里面全面的使用起来,于是发现了一些坑,这里和大家分享一下,顺便说说我是怎样解决的. 首先是图集打包的问题.这个问题在unity5.2版本已经解决了,但在5.2之前确实是一个bug来的.具体的表现是,你把同一个图集标签的散图打包成同一个assetbundle时,这个assetbundle既包含了图集的大图,也包含了散图本身,变成了重复打包,容量暴增.这个问题困扰了我一小段时间,后来尝试着下载了个unity5.2,就没有这个问题了

该选择场内基金还是场外基金,手续费便宜就好吗?最详细的介绍

作者:牛大 | 公众号:定投五分钟 大家好,我是牛大.每天五分钟,投资你自己:坚持基金定投,终会财富自由! 有很多朋友有疑问,购买基金时,是选择场内基金,还是场外基金呢? 首先,牛大先给大家介绍一下两者的主要区别. 1,交易的平台不同 场内基金是在交易所购买的基金,可以使用股票交易软件来购买,当然前提是需要开户.场外基金不需要开户,直接在支付宝.微信等第三方平台就能购买. 2,交易的价格不同 场内基金就像股票一样,交易时间内的价格是实时变动的,买入价格一般不等于收盘价.而场外基金只要是当天3点之

doT.js详细使用介绍

官网: http://olado.github.iodoT.js详细使用介绍 使用方法: {{= }} for interpolation {{ }} for evaluation {{~ }} for array iteration {{? }} for conditionals {{! }} for interpolation with encoding {{# }} for compile-time evaluation/includes and partials {{## #}} for

ThinkPHP 自动创建数据、自动验证、自动完成详细例子介绍(十九)

原文:ThinkPHP 自动创建数据.自动验证.自动完成详细例子介绍(十九) 1:自动创建数据 //$name=$_POST['name']; //$password=$_POST['password'];  ---这个注册页面传过来的POST值 下面用了自动穿件create方法就可以不用这个,会行动绑定 $user =M('User'); $User->create();   //会将传过来的$_POST数据对应到数据库的字段 $user->add();   //就可以直接写入 2:自动验证

show table status like 'table'\G 详细信息介绍

mysql> show table status like'leyangjun'\G *************************** 1. row *************************** Name: leyangjun                 表名字 Engine: MyISAM                 表存储引擎 Version: 10                          版本 Row_format: Dynamic        行格式

iOS—如何申请苹果公司开发者账号流程详细图文介绍(包括邓白氏编码的申请方法详细介绍)

写在开头~ 这是我第一次申请苹果的企业开发者账号,走了很多弯路,网上很多帖子写的不明不白,这次从申请到拿到结束大概花了1个月多点的时间,上个月就申请完了,一直在忙公司项目的事情,所以现在才有时间来写这篇博客,希望能帮助到大家 转载注明出处:http://www.cnblogs.com/northwan/p/4781127.html 正文: 我们要申请开发者账号,首先就需要先注册一个苹果的appleid,然后再这个账号的基础上去继续,这个相信大家都知道 这是申请appleid的地址: https:

Exchange2013 SP1 DAG详细配置介绍

上一篇我们介绍了Exchange2013 sp1的安装及详细配置,今天呢就主要介绍Exchange2013 sp1的DAG配置介绍,那什么是DAG(Database Availability Group)呢,DAG就是数据库可用性组是内置于 Microsoft Exchange Server 2013 中的高可用性和站点恢复框架的基础组件. DAG 是一组邮箱服务器(最多可包含 16 个邮箱服务器),其中承载了一组数据库,可提供从影响单个服务器或数据库的故障中自动执行数据库级恢复的功能. 当然创

psql 工具详细使用介绍

psql 介绍 psql 是 PostgreSQL 中的一个命令行交互式客户端工具, 它允许你交互地键入 SQL 命令,然后把它们发送给 PostgreSQL 服务器,再显示 SQL 或命令的结果. 输入的内容允许来自一个文件,此外它还提供了一些元命令和多种类似 shell 的特性来实现书写脚本,以及对大量任务的自动化工作. 特性:方便快捷.没有图形化工具使用上的一些限制 psql 的简单使用     直接输入 psql 进入到命令行下:       安装数据库时,会自动创建一个与当前操作系统用

iOS———如何申请苹果公司开发者账号流程详细图文介绍(含邓白氏编码的申请方法详细介绍)

因为公司需要,现将之前申请的个人苹果开发者账号会籍迁移到公司名称下 (意思就是之前我们的app 上传到app stroe上面的时候显示的是个人作品,电视迁移完以后,app下面会显示的是公司名称,然后在公司下面可以添加个人开发者名称) 这也是我第一次申请邓白氏编码,在申请之前也找过网上的方法,但是都写的不够全面,看得人不明白,所以在我申请的整个流程中,我将这些过程记录下来,一遍以后有人需要,整个过程花费时间大概一个多月,当然,所有时间都是花在等待上 下面开始记录: 我们是首先有一个Apple开发者