Unity资源打包之Assetbundle

本文原创版权归 csdn janeky 全部。转载请具体注明原创作者及出处,以示尊重。

作者:janeky

原文:http://blog.csdn.net/janeky/article/details/17652021

假设这篇文章对你有帮助,敬请关注作者《Unity手游之路》系列教程。

在手游的运营过程中,更新资源是比不可少的。

资源管理第一步是资源打包。传统的打包能够将全部物件制成预设Prefab。打包成场景。今天我们来一起学习官方推荐的Assetbundle。它是Unity(Pro)提供的资源打包策略。利用AssetBundle,能够将差点儿全部的资源都打包封装,便于client更新下载新的资源。

(转载请注明原文出处http://blog.csdn.net/janeky/article/details/17652021)

  • 创建AssetBundle
1.创建一个空的Prefab,命名Cube,然后创建一个Cube,将其拉到刚创建好的Prefab
2.新建一个脚本ExportAssetBundles.cs(代码来自官方文档),保存在Asset/Editor文件夹下
这时我们将看到Asset以下出现Build AssetBundle From Selection和Build Scene
3.选中预设Cube,执行Build AssetBundle From Selection。这时会弹出一个保存框,将其命名为cube.unity3d(这里为了測试方便,放在c盘。实际项目中。我们是须要将他们放在webserver。供全部client下载更新)
4.新建一个场景scene1.unity,上面放置几个模型,然后保存

5.选中该场景,在之前的ExportAssetBundles.cs脚本中加入打包场景的函数。执行Assets->Build Scene。保存为scene1.unity3d(这里为了測试方便。也放在c盘)

注意事项
a.AssetBundle的保存后缀名能够是assetbundle或者unity3d
b.BuildAssetBundle要依据不同的平台单独打包,BuildTarget參数指定平台,假设不指定,默认的webplayer
  • 载入AssetBundle

我们通过一个简单的代码来演示怎样载入assetbundle,包含载入普通asset和场景。

注意事项
a.LoadFromCacheOrDownload 能够指定版本号。假设本地版本号是新的。将不会从server读取
b.假设是多个资源打包在一起,我们要通过bundle.Load(),载入特定的资源
c.挂载在模型上的脚本也能够一起打包。可是保证脚本在原文件夹也要存在,否则载入出来无法执行。关于怎样更新脚本,我将放在以后的章节中阐述。


  • AssetBundle依赖关系
假设一个公共对象被多个对象依赖。我们打包的时候。能够有两种选取。一种是比較省事的,就是将这个公共对象打包到每一个对象中。这样会有非常多弊端:内存被浪费了。增加公共对象改变了。每一个依赖对象都得又一次打包。

AssetBundle提供了依赖关系打包。

我们通过一个简单的样例来学习

我们在程序载入的时候必须保证先载入公共对象。否则,仅仅能是在各个对象载入成功后,再通过程序手动加入进来。比較繁琐。在实际项目中,因为是团队开发。对象间的依赖关系一般会比較凌乱。最好在开发周期就定好相关的规范约束。方便管理。
  • 总结

这一节的内容偏实际操作,官方文档和雨松的blog中已经有更加具体介绍。假设大家还有不明确的地方。能够结合文档再实际操作一下。

后面的章节,我将花很多其它的时间介绍核心的内容:资源的增量更新。和代码程序的更新

  • 源代码

http://pan.baidu.com/s/1i3BOAPn

  • 參考资料

1.http://www.xuanyusong.com/
2.http://game.ceeger.com/Manual/DownloadingAssetBundles.html

来源:http://www.im286.com/thread-11924518-1-1.html

 

Assetbundle 是Unity Pro提供提供的功能。它能够把多个游戏对象或者资源二进制文件封装到Assetbundle中,提供了封装与解包的方法使用起来非常便利。

1.预设

Assetbundle能够将Prefab封装起来。这是多么方便啊。 并且我也强烈建议大家将Prefab封装成Assetbundle。由于Prefab能够将游戏对象身上带的游戏游戏组件、游戏脚本、材质都封装在一起。

当从server上将Assetbundle下载以后直接Instantiate就能够放入游戏中。

试想一下,假设仅仅能将原始的二进制资源文件放在server上下载,当资源文件完成下载后,须要动态的创建游戏对象、然后动态的将脚本绑定在游戏对象、动态的将贴图赋予游戏对象等等各种动态的操作。

。所以强烈建议使用Prefa,不解释!

。!!



另外。我在举个样例,由于模型有可能会带非常多动画文件,那么这样一组模型资源就可能是多个FBX 文件 和 若干png贴图文件 材质文件。这时我仅仅须要把原始模型放入Prefab中,它就会包括这个模型的全部组件、甚至包括它的动画资源、贴图。

那么例如以下图所看到的,Mode就是模型的Prefab文件。那么我仅仅仅仅须要把Mode这个预设打包成Assetbundle就可以。

当我在server上下载这个Assetbundle而且加载游戏中就能够直接使用了,切换动画、换贴图都能够。



2.二进制文件

也并非Assetbundle中全都要用预设。Assetbundle它也能够将二进制文件直接封装在里面。比方图片、声音、文本信息等等。



3.场景文件

在Unity中能够将一个场景保存在Scene中。Scene就会包括这个场景中的全部。那能不能把Scene也封装成Assetbundle中?答案是能,可是它不能在移动平台上用,由于移动平台上是不能更新脚本的,换句话来说就是即使将脚本绑定在Prefab中,然后下载Assetbundle后,全部脚本是不会运行的,后面说第二种巧妙使用方法。

4.移动平台

上面MOMO已经将Assetbundle 的使用原理大致介绍了一下 ,我们在谈谈移动平台。

脚本不能更新是移动平台下最大的伤,这就意味着开发人员无法绕过App store和 google Play这样的在线商店升级应用程序。

唯一能做到的就是更新资源、举个样例。游戏中在处理版本号升级时,通常会有个大版本号号和一个小版本号号,大版本号号就是 2.0、3.0这样的 版本号须要在AppStore中更新。大版本号主要是升级游戏脚本,然后当小版本号号,比方2.0.1 或2.0.2这样的仅仅是更新游戏中的资源。通过自己游戏的server就能够完毕。通过Assetbundle在自己server上下载,然后适应在游戏中。

假设非要更新脚本,或不得不更新脚本那么仅仅能在Appstore或者google Play去更新大版本号。



移动平台上不能更新脚本。那么Prefab上绑定的脚本怎么办?在不论什么平台上都能够把脚本加入到Prefab上,然后打包成Assetbundle。仅仅有移动平台上有点特殊,比方将Test.cs这条脚本绑定在Prefab中。最后程序通过server下载这个Assetbundle ,当加载project中这条脚本是不会被运行的。

可是假设本地project有Test.cs这条脚本。那么Unity会自己主动将这条脚本绑定在下载的Prefab中。而且他们运行的很好。

假设本地project中没有Test.cs这条脚本。那么Prefab上的脚本是永远都不会运行的。有时我们会在脚本中写一些Public的变量,有可能不同的Prefab上绑定的是同样的脚本,仅仅是Inspector 脚本中的public參数不同。别操心这一点Assetbundle 中的Prefab也是没问题,所以说仅仅要大版本号中的脚本没问题,在小版本号中仅仅更新游戏资源是一点问题都么有的。

5.移动优化

之前我们说过能够将游戏中的某个游戏对象封装成Assetbundle,也能够将游戏中的整个场景也封装成Assetbundle。可是我觉得须要巧妙的使用封装场景。由于场景中肯定有非常多公用的模型,假设打包场景的话那么内存与size就是 公用模型的size * N个场景,想想事实上挺恐怖的。

事实上我们能够巧妙的使用。首先把场景中公用的部分和私有的部分统统放入Unity, 然后烘培整个场景。 当场景烘培完成后把公用的模型部分在拿出去,场景仅仅仅仅保留私有的模型。还能够做一个工具将公用模型在场景中的坐标保存在XML中(每一个场景文件会相应一个公用模型的XML信息),最后在将公用的模型分别封装在别的Assetbundle中。



server上提供每一个场景的Assetbundle ,和公用模型的Assetbundle,一般公用模型的Assetbundle能够放在常驻内存中(可能使用频繁、依据项目的不同而定)场景Assetbundle下载完毕后。现加载场景然后在依据场景相应的XML信息将公用模型部分动态的在加入到场景中,这样就完毕了一个场景的构建。

6.总结

对游戏中全部资源进行打包。比方按类型分为五个大部分 界面,模型,特效,声音。场景。脚本。



界面部分:

公用资源包(可复用的资源包)和 每一个界面独有得资源包(不可复用的资源包)统一使用Prefab 打包成.assetbundle 二进制格式。



模型部分:

按角色分类。统一使用Prefab 打包成.assetbundle 二进制格式。 模型部分包含模型文件与动画文件。每个模型文件相应一组动画文件。(假设模型须要换装还需提供相应换装的模型与贴图) ,由于unity4的重定向动画不支持动态载入。所以眼下不须要考虑 不同大小 不同规格 不同性别 的模型重定向动画。



特效部分: 统一使用Prefab 打包成.assetbundle 二进制格式。

声音部分: 统一使用Prefab 打包成.assetbundle 二进制格式。

场景部分:场景和前面的有点差别。场景须要导出烘培的光信息而且仅仅能烘培场景之上永远不动的模型,可是这些永远不动的模型有可能会同一时候在多个场景中使用,所以场景烘培完成后要把反复使用的对象删除,(执行游戏在动态的载入进来)场景中仅仅保留该场景中永远不会变的模型,以及烘培的光照信息。 打包场景后会生成.unity3D 二进制格式。它和 assetbundle 打包方式是不同的。

(另外,也能够考虑 json xml 二进制 来动态组装场景)。



脚本部分:假设Prefab上是带脚本打包Assetbundle的话 脚本是不会被执行的(移动平台), 可是unity有一个技巧。Prefab上的脚本 假设本地有的话它会把本地的同名脚本绑定在Prefab对象上,它会非常好的执行。

Prefab打包技巧: Prefab打包时自身是不占多少空间的 <=1KB 可是Prefab上是能够关联 这五大部分 “界面,模型,特效,声音,场景,脚本”以及在Hierarchy视图中 坐标/缩放/旋转。 关联这些信息以后就会非常大。所以为了避免资源的浪费尽量避免Prefab反复关联。

一个prefab以下能够同一时候关联多个游戏对象 ,这里举个样例假设你的 Prefab以下放了一个模型 它的大小可能是500k ,在 Prefab以下放了十个全然同样模型 它的大小可能是501k 。

假设Prefab以下放了两个不同的模型,它的大小可能就会是 500k x 2 的size ,也就是说Prefab与关联的数量是无关的 。

加密部分: assetbundle 是能够转换成 字节数组 ,client与server约定一组解密 字节数组的算法就能够实现资源加密。



大版本号升级:

unity的版本号升级事实上主要是升级主程序中的脚本。 由于全部的资源都是assetbundle 和 .unity3d 这些资源放在本地或者server 解包的方式是全然一样,所以理论上我们的主程序包的大小能够做到非常小,能够非常好设置把多少资源放在包里 或者把所少资源放在server上。在执行的时候服务端应该把全部 assetbundle 和 .unity3d的资源文件的下载地址列表返回给client。

小版本号升级:

小版本号升级也就是更新资源,由于不能更新脚本, 在登陆的时候服务端应该把全部 assetbundle 和 .unity3d的资源文件的下载地址列表返回给client。

还有个须要考虑的地方。比方如今大版本号是2.0.0 。小版本号已经是2.0.5 ,用户的手机上是一个1.5.0的包。 此时用户在打开游戏的时候 应当强制它去appstore中去下载大版本号2.0.0 ,当用户完成下载后登陆游戏,此时server告诉client如今已经是2.0.5的小版本号了,这时候client去下载相应小版本号的全部 assetbundle 和 .unity3d文件地址列表。



增量更新:理论上增量更新是可行的。由于unity不能更新脚本。所以在处理增量更新的话 须要在代码中做能够兼容增量更新的可能。



由于Assetbundle这块的代码比較多。我还是决定分成两篇文章来写。这篇文章先说原理、下篇文章说代码。欢迎大家来讨论!

前几天我和Unity鑫哥聊天,他告诉我IOS上是无法执行时更新脚本、可是Android上是能够执行时更新脚本。我回家也试了一下可是没能成功。后来我考虑即使成功了项目中我也不打算那么做,由于这样Android和IOS 做起来的区别就太多了, 另外Unity商店中有一个处理执行时更新脚本的插件 unityLua 大家能够去研究研究。

原文地址:https://www.cnblogs.com/wzjhoutai/p/7084346.html