unity3d assetbundle.unity unloadasset 什么时候调用

本文内容主要翻译自下面这篇文章
& A guide to AssetBundles and Resources
本部分讨论AssetBundle实际应用中一切潜在的问题和解决方案。
1.1&&& 管理加载的资源
在内存敏感的环境里面要严格控制加载Object的大小和数量。当Object从当前激活场景中移除时,Unity不会自动卸载他们。清除Asset只有在特殊的时刻被触发。当然也可以手动触发。
AssetBundle子什么也要仔细管理。从文件加载的AssetBundle占用的内存最小,一般不超过10到40KB。但是当大量AssetBundle出现的时候还是会出现问题。
因为大部分项目运行用户重复体验相同的内容,比如重玩一个关卡,所以知道什么时候加载和卸载AssetBundle很重要。如果一个AssetBundle被不正确的卸载,会造成Object占用双倍内存,在某些情况下还会造成别的不可预期的问题。比如贴图丢失。
理解了AssetBundle.Unload方法的参数true和false的区别对应管理assets和AssetBundle非常重要。这个api卸载掉被调用的AssetBundle的头信息。里面的参数会指定是否同时卸载从AssetBundle里面实例化的Objects。如果参数为true,则从这个AssetBundle里面创建的所有objects都被立即卸载,即使正在被当前的场景使用。
比如下图所示
材质M从AssetBundle AB里面加载的,而且M正在当前场景中被使用。如果Unload(true)被调用,则M会从当前场景移除并销毁掉。但是如果调用的是Unload(false),则AB的头信息被卸载了但是M仍然留在场景里面起作用。但是M和AB的联系呗打断了。如果AB重新被加载,新的objects拷贝会重新加载进内存。
如果AB后来又被加载的话,新的一份AssetBundle的头信息拷贝到内存。但是M不再是从新的AB里面加载的。Unity不会给M和新的AB建立连接。
如果这是再次调用LoadAsset方法重新加载M,Unity不会任务原来的那个M是从AB里面数据的实例化,而是从新加载一份新的M。导致场景里面有两份一样的M。
对很多项目来说,这是不期望的行为。大部分项目都才用AssetBundle.Unload(true)和措施来确保对象不会被复制。两个常用的方案是
找一个应用程序生命周期某个设计好的时点卸载所有的AssetBundle。比如关卡切换或者在过载场景。这是最简单常用的选项。
维护单个对象的object的引用计数。当一个AssetBundle的所有对象没有被使用时卸载AssetBundle。
如果一个应用必须采用Unload(false),这些Objects只能用两种方式卸载:
确保没有对这个对象的引用,无论是代码还是场景里面。然后调用 Resources.UnloadUnusedAssets.
以非附加的方式加载一个场景。这回自动销毁当前场景里面的objects然后调用1里面的方法。
如果项目有设计好的点,用户在这里等待对象的加载和卸载。比如游戏模式或者关卡之间的切换,这个时点就可以用来卸载不需要的Objects并加载新的对象。最简单的方式就是资源以场景的方式分割。然后把每个场景及其里面的依赖打包到AssetBundle里面。程序可以加入一个加载场景,在这里卸载老场景里面的对象,然后加载包含新场景的AssetBundle。显然这是一个简单的流程,一些项目需要更复杂的AssetBundle管理。这里没有统一的设计样式,每个项目都不一样。当考虑怎么样Objects分组打包时,如果对象总是一起加载和更新,就可以考虑打包进一个AssetBundle。
比如一个角色扮演游戏,就可以把地图和过场动画以场景分组打包。但是有些对象所有的场景都需要。比如头像,游戏UI和角色模型以及贴图等,后面的对象可以打包进第二套AssetBundle,并且在游戏开始时加载,然后整个生命周期都存在。
另外一个问题就是如果从一个已经卸载的AssetBundle里面加载Object,就会加载失败,在unity的编辑器的Hierarchy面板里面显示一个丢失的对象。这个问题经常出在线unity丢失了绘图上下文而需要重新获取时。比如一个移动应用被挂载了或者用户锁定了他的pc。这时候,unity会重新加载贴图和着色器到GPU里面。如果AssetBundle已经失效了(被卸载),这个应用程序就会用洋红色渲染这个对象。
有两种方式分发AssetBundle到客户端:一种直接放到安装包里面另外一种是安装后下载。那种方式根据项目类型来选用。移动项目一般采用安装后下载。控制台和PC项目一般把AssetBundle随安装包一些分发。
正确的架构使得安装后仍可以打补丁或者修正内容而不管开始AssetBundle时如何分发的。
1.2.1&&&&&&& 同项目一起分发
这是最简单的方式,因为不需要附加的下载代码。采用这种方式有两个主要理由:
减少项目编译次数同时可以开发迭代也简单。因为如果AssetBundle不需要同应用隔离开来的话,可以直接把他们存储到streamingassets目录。
开始就分发可更新资源,就节约了终端用户的时间。Streamingassets不适合这种需求。如果不想自己写一个下载和缓存管理器,那么初次可更新内容可以从streaming assets加载到Cache里面。
1.2.1.1& Streaming Assets
如果想在安装后就包含内容的最简单方式就是把该内存放到/Assets/StreamingAssets/目录。在编译的时候,任何在该目录的内容都会被拷贝到最终的应用程序里面。这个目录可以用来存储任何内容而不仅仅是AssetBundle。
运行时,完整路径可以通过Application.streamingAssetsPath属性来访问。在大部分的平台上面他可以通过LoadFromFile来加载里面的AssetBundle。但是在安卓平台上面,这个属性指向一个压缩的jar文件。甚至AssetBundles都是被压缩了。这种情况下,WWW.LoadFromCacheOrDwonLoad可以用来加载AssetBundle。当然也可以自己写代码来解压jar报,然后抽取AssetBundle到可读的本地目录。
注意Streaming Assets在某些平台是不写的。如果AssetBundle安装后需要更新。需要使用WWW. LoadFromCacheOrDwonLoad或者自己写下载器。
1.2.2&&&&&&& 安装后下载
在移动平台上常用该方法。这允许安装后内容可以更新或优化而不用用户重新下载整个应用。在移动平台上面,应用审批流程总是很麻烦的。因此更新系统是必不可少的。
最简单的方式就是讲AssetBundle放到web服务器上面。然后通过WWW或者UnityWebRequest下载。unity会自动存储下载好的AssetBundles。如果下载的是LZMA压缩的内容。unity会解压存放。如果是LZ4压缩的。则下载后也是压缩存储的。如果缓存不足,unity会移除最少使用的AssetBundle。
但是WWW. LoadFromCacheOrDwonLoad是有瑕疵的,正如前面所述,这个在下载时候会消耗AssetBundle数据大小的内存,可能会导致内存问题。有三种方式来避免
保证AssetBundle够小。
5.3或者更新的版本,用UnityWebRequest。
自定义下载器。
一般建议尽可能使用UnityWebRequest,或者5.2以及前面的版本使用WWW,只有内建的系统在内存消耗缓存行为或者性能不可接受的情况下才建议使用自定义下载系统。
下面是不适合使用WWW者UnityWebRequest的情况:需要更好地控制AssetBundle缓存。项目需要自定义压缩策略。项目需要平台相关的API。比如离线下载比如IOS后台任务可以下载。或者AssetBundle需要通过SSL协议下载。
1.2.3&&&&&&& 内建的AssetBundle的缓存
在使用WWW和UnityWebRequest时下载的AssetBundle被存储在内建的缓存里面。两个API都有一个重载的版本,接收一个AssetBundle版本号,这个数字不是存储在AssetBundle里面。而且不是AssetBundle系统生成的。
缓存系统跟踪这个版本号。调用api的时候,缓存系统首先检查资源十分存在,如果有,则比较上一次缓存的版本号。如果匹配,则从缓存加载,如果不匹配,或者没有缓存,则unity去下载一个新版本,并同这个版本号关联起来。
AssetBundle使用名字来认证的而不是下载的URL。这意味着相同名字的AssetBundle可以存在不同的位置。比如一个AssetBundle可以存储在多个服务器上面或者CDN上。只要这个名字是一样的。缓存系统就认为他们是相同的AssetBundle。
给AssetBundle分配版本号是开发者的责任。大部分应用使用unity5的assetbundleManifestApi。这个API生成通过AssetBundle的内容MD5哈希值为该AssetBundle生成一个版本号。当AssetBundle改变的时候,他的哈希值也变化了。这就意味着AssetBundle需要下载。注意unity缓存系统并没有删除就得AssetBundle,直到cache被填满。unity后续版本可能会修复这个问题。
1.2.4&&&&&&& 自定义下载(略)
1.3&&&&&&&&& Asset 分配策略
怎么分配项目的资源到不同的AssetBundle不是那么简单。一个简单的诱人的方案就是每个对象放进自己的AssetBundle或者只用一个单独的AssetBundle。但是这些方案都有缺点:
有过少的AssetBundle:增加了运行时内存消耗。增加了加载时间,需要很大的下载。
如果是过多的AssetBundle呢?增加了编译时间,增加了开发的复杂性,增加了总共的下载时间。
怎么把对象分组到AssetBundle的关键思考点在于逻辑实体对象类型和和并发的内容。
要知道一个项目可能会混合这些分类策略。比如一个项目会把不同平台的ui打包到各自的AssetBundle。把不交互的内容按场景打包。厦门是一些好的建议:
把经常更新的内容和不变的内容打包到不同的AssetBundle。
把同时加载的内容打包到一起。比如一个模型和他的纹理以及动画。
如果一个对象依赖多个不同的AssetBundle里面的对象,把这些资源移到一个单独的AssetBundle。
把子对象和父对象分组到一起。
如果两个对象不会一起加载。则打包到不同的AssetBundle。
如果对象是同一个对象的不同的导入设置版本。考虑使用AssetBundle变量替代。
如果上述规则遵守了,然后把一个AssetBundle每次只有少于50%的内容被加载的继续分割。把一些小的AssetBundle(少于5到10个assets)进行重组一个AssetBundle。
1.3.1&&&&&&& 逻辑实体分组
这个策略是按照功能分组。应用的不同部分被打包进不同的AssetBundle。
比如打包所有UI的纹理和布局在一起。打包所有角色的贴图模型和动画在一起。
1.3.2&&&&&&& 类型分组
这是最简单的策略。相似类型的打包进相同的AssetBundle。比如声音文件打包到一个AssetBundle。不同的语言文件打包进一个AssetBundle。
1.3.3&&&&&&& 并发内容分组
同时加载的内容打包一起。
1.4&&&&&&&&& 用AssetBundles打补丁
AssetBundle打补丁简单的只要重新下载一个新的AssetBundle替代旧有的就可以了。只要传递一个不同的版本号给API。更困难问题是检测什么时候需要打补丁。一个打补丁系统需要2个信息。
当前下载的AssetBundle和版本信息列表。
服务器上面的AssetBundle和版本信息列表。
补丁系统需要下载服务端列表,同本地比较,丢失的或者版本不匹配的都要重新下载。Unity5 AssetBundle系统在编译AssetBundle完成之后生成一个附加的AssetBundle。这个AssetBundle包含 AssetBundleManifest对象。这对象包含了AssetBundle和哈希列表。也可以自己定制检测AssetBundle改变系统,比如用Json系统和标准的C#校验和类MD5.
1.5&&&&&&&&& 常见陷阱
1.5.1&&&&&&& Asset复制
当一个Object打包进一个AssetBundle时,unity5 会自动检查所有的依赖Objects。依赖信息被用来决死你个这些Objects是否包含到一个AssetBundle。
显式指定一个对象打包到一个AssetBundle时,这个对象只被打包到指定的AssetBundle。显式指定是指在编辑器里面AssetBundle属性栏设置了一个非空值。
如果一个Objects没有显式指定一个AssetBundle,则会被打包进所有依赖他的AssetBundle里面。
如果两个Object被打到不停地AssetBundle,但是这两个都引用一个共同的Object,这个Object却没有设置打包信息,那么这个Object会被拷贝到两个AssetBundle里面。这复制的两个也会单独实例化。即会增加应用的AssetBundle的尺寸。如果程序加载两个父对象,也有有2份这个子对象的单独内存拷贝。
解决方法:
确保打包到不同的AssetBundle没有共享的依赖。有共享依赖的Objects打包到同一个AssetBundle。但是如果项目有非常多的共享依赖,这就变得不可行了。他会造成一个单一的AssetBundle。带来下载和效率问题。
保证有共享依赖的AssetBundle不会同时加载。但仍然会加大程序尺寸。
把依赖的Objects打到自己的AssetBundle里面。这消除了复制问题,但是带来了复杂性。应用程序必须跟踪依赖。
Unity5用AssetDataBase来跟踪依赖。他位于UnityEditor命名空间。这个Api只能在Editor环境而不能在运行时使用。AssetImporter API可用来查询某个Object被赋予哪个AssetBundle。联合使用这两个API。可以写一个编辑器脚本确保所有的直接和间接依赖都赋予AssetBundles或者共享的依赖都被赋值到某个AssetBundle。建议项目使用这两个API。
1.5.2&&&&&&& 图集精灵复制
接下来讨论unity 5在计算自动生成的图集精灵的依赖时的奇怪行为。Unity5.2.2p4修复了这个行为。
Unity5.2.2p4,5.3或更新
任何自动生成的精灵图集会被赋给包含这个生成sprite对象的AssetBundle。如果这个精灵Objects打包到多个AssetBundle,那么这个图集就不会打包到一个AssetBundle,而是被复制。如果精灵对象没有赋值给一个AssetBundle,那么就不会被打包。为了保证不复制,需要检查这个图集下所有的精灵都会被打包到同一个AssetBundle。
Unity5.2.2p4或者更老的版本
自动生成的图集不会赋值到某个AssetBundle。因此他们会包含到任何引用他们精灵的AssetBundle中。因为这个问题建议升级到更高的unity版本。对于不能升级的项目,建议:
1简单的方式就是不要用内建的精灵打包器。
2难一点的方式就是把所有的使用这个图集的对象打包到同一个AssetBundle。
1.6&&&&&&&&& AssetBundle Variants
1.7&&&&&&&&& 压缩与否?
是否压缩需要仔细考虑:
加载时间是否是关键因素?未压缩的加载时间会快很多。但是从远程下载压缩的资源也会比未压缩的的块。
编译时间是否是关键因素?LZMA和LZ4编译时非常慢。如果项目有很多AssetBundle,则要花掉大量的时间。
应用程序尺寸是否关键因素?
内存消耗是否是关键因素?
下载时间是否是关键因素?
1.8&&&&&&&&& AssetBundle和WEBGL
unity强烈建议WEBGL项目不要使用压缩的AssetBundle。因为unity5.3在主线程上解压AssetBundle。(下载AssetBundle会通过XMLHttpRequest委托给浏览器。不在主线程上)这意味着在WEBGL里面加载压缩的资源非常消耗。
记住这些,你就会避免LZMA格式,而采用LZ4格式。因为后者的解压很高效。如果你在意资源大小,那就采用lz4来分发,并且配置服务端支持gzip压缩。
阅读(...) 评论()Unity3D研究院之Assetbundle的实战(六十三) | 雨松MOMO程序研究院
我的图书馆
Unity3D研究院之Assetbundle的实战(六十三) | 雨松MOMO程序研究院
上一篇文章中我们相惜讨论了Assetbundle的原理,如果对原理还不太了解的朋友可以看这一篇文章:&本篇文章我们将说说assetbundle是如何实现的。
1.创建Assetbundle
& & & & &无论是模型资源还是UI资源,最好是先把他们放在Prefab中,然后在做成Assetbundle。我们以模型来举例,Assetbundle中可以放一个模型、也可以放多个模型,它是非常灵活了那么最需要考虑的就是模型空间占用的问题。
比如我们有两个完全一样的模型,但是他们身上绑定的脚本不一样,此时需要把这两个模型放在两个不同Prefab中。如下图所示,我们分别对这两个Prefab打包,我们可以清晰的看到两个相同的Prefab打包在一起只占1M空间,而将他们分别打包会占1 1 = 2M空间。 Prefab在打包的同时会把模型身上的所有材质、贴图、组件、脚本全部包含进去。
& & & & &由此可得相同的模型尽量打包在一起,他们会公用一套资源文件。不相同的模型尽量分开打包,相同模型具有不同的脚本、组件的话把他们放在不同的Prefab中,最后把这些Prefab一起打包在一个Assetbundle中。如下图所示,现在Project视图中选择需要打包的Prefab,然后在导航菜单栏中选择Create Assetbundles Main表示分别打包、Create AssetBundles All表示将他们打包在一起。
& & & & 这两个prefab文件都指向了同一个模型,为了让它俩有所区别,我给它俩绑定了相同的脚本,但是脚本中的参数是不同的。在编辑器上给每个Prefab赋值一个不同的名子,然后在Awake方法中进行输出。
12345678910111213
using UnityEngine;using System.Collections;public class Script : MonoBehaviour { public string name; void Awake ()
{ Debug.Log('my name is '
Create Assetbundles Main : 分开打包,会生成两个Assetbundle。
1234567891011121314151617181920212223242526
[MenuItem('Custom Editor/Create AssetBunldes Main')] static void CreateAssetBunldesMain () {&&&&&&&&//获取在Project视图中选择的所有游戏对象 Object[] SelectedAsset = Selection.GetFiltered (typeof(Object), SelectionMode.DeepAssets);&&&&&&&&//遍历所有的游戏对象 foreach (Object obj in SelectedAsset)
{ string sourcePath = AssetDatabase.GetAssetPath (obj); //本地测试:建议最后将Assetbundle放在StreamingAssets文件夹下,如果没有就创建一个,因为移动平台下只能读取这个路径 //StreamingAssets是只读路径,不能写入 //服务器下载:就不需要放在这里,服务器上客户端用www类进行下载。 string targetPath = Application.dataPath
'/StreamingAssets/'
'.assetbundle'; if (BuildPipeline.BuildAssetBundle (obj, null, targetPath, BuildAssetBundleOptions.CollectDependencies)) {&& Debug.Log(obj.name
'资源打包成功'); }
{ Debug.Log(obj.name
'资源打包失败'); } } //刷新编辑器 AssetDatabase.Refresh ();
最核心的方法其实就它:
BuildPipeline.BuildAssetBundle (obj, null, targetPath, BuildAssetBundleOptions.CollectDependencies)
参数1:它只能放一个对象,因为我们这里是分别打包,所以通过循环将每个对象分别放在了这里。
参数2:可以放入一个数组对象。
默认情况下打的包只能在电脑上用,如果要在手机上用就要添加一个参数。
Android上:
BuildPipeline.BuildAssetBundle (obj, null, targetPath, BuildAssetBundleOptions.CollectDependencies,BuildTarget.Android)
BuildPipeline.BuildAssetBundle (obj, null, targetPath, BuildAssetBundleOptions.CollectDependencies,BuildTarget.iPhone)
另外,电脑上和手机上打出来的Assetbundle不能混用,不同平台只能用自己的。
Create AssetBundles All:将所有对象打包在一个Assetbundle中。
12345678910111213141516171819202122
[MenuItem('Custom Editor/Create AssetBunldes ALL')] static void CreateAssetBunldesALL () { Caching.CleanCache (); string Path = Application.dataPath
'/StreamingAssets/ALL.assetbundle'; Object[] SelectedAsset = Selection.GetFiltered (typeof(Object), SelectionMode.DeepAssets); foreach (Object obj in SelectedAsset)
{ Debug.Log ('Create AssetBunldes name :'
obj); } //这里注意第二个参数就行 if (BuildPipeline.BuildAssetBundle (null, SelectedAsset, Path, BuildAssetBundleOptions.CollectDependencies)) { AssetDatabase.Refresh (); } else { } }
&两次打包完毕后,在StreamingAssets文件夹中就看到了这三个assetbundle文件。
2.读取Assetbundle&
& & & &然后我们来学习如何运行时读取Assetbundle,Assetbundle是可以同时放在服务器或者本地的,无论放在哪里两种下载读取的方式是完全一样的。所以我建议在做unity项目的时候开始就把资源放在Assetbundle中在本地来做,等做的差不多了直接把Assetbundle放在服务器上,因为两种读取的方式完全一样,这样以后更新资源会方便很多。然后是读取,并且加载到游戏中。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
using UnityEngine;using System.Collections;public class RunScript : MonoBehaviour{ &&&&//不同平台下StreamingAssets的路径是不同的,这里需要注意一下。 &&&&public static readonly string PathURL =#if UNITY_ANDROID 'jar:file://'
Application.dataPath
'!/assets/';#elif UNITY_IPHONE Application.dataPath
'/Raw/';#elif UNITY_STANDALONE_WIN || UNITY_EDITOR 'file://'
Application.dataPath
'/StreamingAssets/';#else&&&&&&&&string.Empty;#endif void OnGUI() { if(GUILayout.Button('Main Assetbundle')) { StartCoroutine(LoadMainGameObject(PathURL
'Prefab0.assetbundle')); StartCoroutine(LoadMainGameObject(PathURL
&&'Prefab1.assetbundle')); } if(GUILayout.Button('ALL Assetbundle')) { StartCoroutine(LoadALLGameObject(PathURL
'ALL.assetbundle')); } } //读取一个资源 private IEnumerator LoadMainGameObject(string path) { WWW bundle = new WWW(path); yield return bundle; //加载到游戏中 yield return Instantiate(bundle.assetBundle.mainAsset); bundle.assetBundle.Unload(false); } //读取全部资源 private IEnumerator LoadALLGameObject(string path) { WWW bundle = new WWW(path); yield return bundle; //通过Prefab的名称把他们都读取出来 Object&&obj0 =&&bundle.assetBundle.Load('Prefab0'); Object&&obj1 =&&bundle.assetBundle.Load('Prefab1'); //加载到游戏中
yield return Instantiate(obj0); yield return Instantiate(obj1); bundle.assetBundle.Unload(false); }}
&这里我们详细的说说 下载类WWW
WWW bundle = new WWW(path);
这样的做法是通过一个路径进行下载(无论是服务器路径还是本地路径下载操作都一样)但是bundle只能保存在内存中,也就是退出游戏在进入还得重新下,很显然在游戏中我们不能使用这种方式。
1234567891011
private IEnumerator LoadMainCacheGameObject(string path) { WWW bundle = WWW.LoadFromCacheOrDownload(path,5); yield return bundle; //加载到游戏中 yield return Instantiate(bundle.assetBundle.mainAsset); bundle.assetBundle.Unload(false); }
使用的方法是WWW.LoadFromCacheOrDownload(path,5);
参数1:服务器或者本地下载地址
参数2:版本号
& & & & &Unity会下载Assetbundle本地中,它的工作原理是先通过(版本号和下载地址)先在本地去找看有没有这个Assetbundle,如果有直接返回对象,如果没有的话,在根据这个下载地址重新从服务器或者本地下载。这里版本号起到了很重要的作用,举个例子,同一下载地址版本号为1的时候已经下载到本地,此时将版本号的参数改成2 那么它又会重新下载,如果还保持版本号为1那么它会从本地读取,因为本地已经有版本号为1的这个Assetbundle了。你不用担心你的资源本地下载过多,也不用自己手动删除他们,这一切的一切Unity会帮我们自动完成,它会自动删除掉下载后最不常用的Assetbundle ,如果下次需要使用的话只要提供下载地址和版本后它会重新下载。
& & & & 我们在聊聊Assetbundle 中的脚本,在移动平台下Assetbundle里面放的脚本是不会被执行的,还记得我们打包前给两个Prefab挂上了脚本吗?在手机上将Assetbundle下载到本地后,加载进游戏中Prefab会自动在本地找它身上挂着的脚本,他是根据脚本的名来寻找,如果本地有这条脚本的话,Prefab会把这个脚本重新绑定在自身,并且会把打包前的参数传递进来。如果本地没有,身上挂的条脚本永远都不会被执行。
& & & 在Prefab打包前,我在编辑器上给脚本中的变量 name 赋了不同值,当Prefab重新载入游戏的时候,它身上脚本的参数也会重新输出。
如果你的Assetbundle中的Prefab上引用的对象,那么这样做就会出错了,你需要设定他们的依赖关系。或者运行时通过脚本动态的载入对象。
/Documentation/ScriptReference/BuildPipeline.PopAssetDependencies.html
/Documentation/ScriptReference/BuildPipeline.PushAssetDependencies.html
像这样重新打包就可以。
3.打包场景
& & &上面我们说过了打包Prefab,其实我们还可以把整个场景进行打包,因为移动平台不能更新脚本,所以这个功能就会有所限制,我的建议是烘培场景、然后把多个场景可复用的对象移除,场景中只保留独一无二的游戏对象,然后在打包场景,运行游戏时载入场景后,在动态的将之前移除的对象重新添加进来。
可以参考 :&
1234567891011
[MenuItem('Custom Editor/Create Scene')] static void CreateSceneALL () { //清空一下缓存 Caching.CleanCache(); string Path = Application.dataPath
'/MyScene.unity3d'; string&&[]levels = {'Assets/Level.unity'};&&&& //打包场景&&&& BuildPipeline.BuildPlayer( levels, Path,BuildTarget.WebPlayer, BuildOptions.BuildAdditionalStreamedScenes); AssetDatabase.Refresh (); }
& & & & & 不同平台下需要选择 &BuildTarget.Android 和 BuildTarget.iPhone 。 切记这段代码是把Level.unity常见文件打包到MyScene.unity3d文件中,所以在解包的时候也应当是先解开MyScene.unity3d,然后在去加载Level.unity场景,无需在ProjectSetting中注册新场景。
private IEnumerator LoadScene() { WWW download = WWW.LoadFromCacheOrDownload ('file://' Application.dataPath
'/MyScene.unity3d', 1); &&yield return download; &&var bundle = download.assetBundle;&& &&Application.LoadLevel ('Level'); }
& & & & & 在测试情况下你可能会频繁的打包生成Assetbundle,如果忘记改版本号的话可能会读取之前的缓存,可能就会看不到新的效果,所以我建议在bunild Assetbundle的时候强制清空一下缓存。
Caching.CleanCache();
最后点击按钮进行加载Assetbundle和 Scene吧。
最后是下载地址:
欢迎大家一起学习,欢迎给我留言、欢迎一起讨论,祝大家学习愉快 啦啦啦啦。
2014年10月补充
WWW.LoadFromCacheOrDownload&这个方法建议大家以后不要再用了
因为是异步方法,而且还占用内存。
强烈建议使用AssetBundle.CreatFromFile 它是一个同步方法。现在IOS 和 android 都支持了,强烈建议用。
打包的时候需要选择不压缩。
//打包场景 BuildPipeline.BuildStreamedSceneAssetBundle(levels, path, target, BuildOptions.UncompressedAssetBundle)) //打包资源 BuildPipeline.BuildAssetBundle(null, assets, path, BuildAssetBundleOptions.UncompressedAssetBundle | BuildAssetBundleOptions.CollectDependencies, target);
因为不压缩, 所以就需要我们自己来压缩资源了, 可以用LZMA 和 GZIP来进行压缩。
1.打包出来的Assetbundle我们自己用LZMA压缩,上传到服务器上。
2.IOS或者Android下载这些assetbundle
3.解压缩这些assetbundle并且保存在Application.persistentDataPath 目录下。
4.以后通过AssetBundle.CreatFromFile &读取assetbundle。
此法确实可行,我们已经在实际项目中轰轰烈烈的使用了。。
本文固定链接:
转载请注明:
雨松MOMO提醒您:亲,如果您觉得本文不错,快快将这篇文章分享出去吧 。另外请点击网站顶部彩色广告或者捐赠支持本站发展,谢谢!
最后编辑:作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
如果您愿意花10块钱请我喝一杯咖啡的话,请用手机扫描二维码即可通过支付宝直接向我捐款哦。
TA的最新馆藏
喜欢该文的人也喜欢

我要回帖

更多关于 unity5 assetbundle 的文章

 

随机推荐