| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 游戏开发 -> Unity加载优化-将基于LZMA的ab压缩方案修改为LZ4压缩的过程 -> 正文阅读 |
|
[游戏开发]Unity加载优化-将基于LZMA的ab压缩方案修改为LZ4压缩的过程 |
# 观前提示本文适合需要了解LZMA以及LZ4进行ab打包方案同学,以及会将一些资源管理的方案。如果恰好你也用xlua-framework,那就更适合你了。 # 优化起因最近新游戏在Iphone6上出现了闪退的情况,出现闪退是在加载完成后的一瞬间,用脚指头想都知道内存超过上限了,查了下Iphone6内存为1GB,可使用最大内存上限为645M,理应是一个很高的内存值,由于新游戏是一款3d大地图城建游戏,模型建筑特别多,内存也出现溢出。这让我不得不想办法优化内存以及加载速度,一般的内存优化是从纹理,模型,动画这些资源下手,但是还没等我查到这一步,就发现之前使用的框架存在很大的内存优化空间,所以就有了这一篇优化文章。 # 优化前的情况之前使用的框架叫xlua-framework,框架逻辑还是挺清晰的,可以再次基础上修改出比较好的框架。这次也是基于此进行优化,虽然是基于框架进行优化,但是主要还是将LZMA到LZ4压缩方案需要注意及修改的地方。 老框架使用LZMA压缩方式,游戏加载的时候先通过UnityWebRequestAssetBundle接口对AssetBundle进行全量加载,加载后缓存AB包,然后再将AB包内所有资源进行缓存。这个时候AB包,以及AB包内所有资源都在内存中。另外通过引用计数去维护资源,在切换场景的时候尝试卸载没有使用的资源,如果一个AB没有一个资源被使用就把这个AB卸载。 ### 问题1.LZMA采用流压缩方式(stream-based),压缩率会比LZ4更高,体现在包体更小,但是问题也很严重。LZMA只支持顺序读取,所以加载AB包时,需要将整个包解压,会造成卡顿和额外内存占用。这也是为什么在有些复杂UI上首次打开会造成卡顿。 2.加载AB包后将所有资源进行了缓存,导致了如果AB包资源利用率在短时间利于率不高的时候,造成了很高的内存浪费。 3.一套引用计数规则非常复杂,当资源过多的时候建立引用关系都是很费时的,其中的常驻包的设置逻辑也是非常具有不确定性。 ### 基于LZ4优化方案对应解决了什么1.LZ4采用块压缩方式(chunk-based),块压缩的数据被分为大小相同的块,被分别压缩,虽然压缩率不及LZMA,但是读取效率比LZMA高非常多 2.LZ4压缩的AB包,使用LoadFromFile()或LoadFromStream()只会加载AB包的Header,相比于直接加载解压整块AB包,效率更进一步提高。另外一个很重要的点,由于可以只加载Header,因此AB包可以做到一旦加载到内存后就再不卸载,此时只需要管理从AB包中读取出来的资源的生命周期。 3.对于之前使用引用计数的优化,由于Unity原本资源管理就是使用引用计数去维护,这里再建立一套内部的引用计数,不仅多余而且很浪费CPU资源,而且效果不一定很好。这个时候我们可以建立一套弱引用管理体系,通过弱引用去持有资源,在触发Resource.UnloadUnusedAssets()再去清除弱引用失效的对象。 下面这张图是AB资源及其内部资源的生命周期 # 优化步骤## 将LZMA的压缩方式修改为LZ4将打包参数添加BuildAssetBundleOptions.ChunkBasedCompression即可
## 修改AB包读取方式
这里需要注意一点的就是,LoadFromFileAsync与WWW或UnityWebRequest区别在于是在windows下不需要file://前缀 下面这个回答来源:Unity 5.3 bundles - "Unable to open archive file" - Unity Forum ? ?## 修改引用计数为弱引用管理在一个资源被加载好后,为其建立一个WeakReference对象,如果下次还要加载相同资源,直接返回这个弱引用的Target对象。在卸载场景后,将失效的弱引用清除即可。 ### 为什么能用弱引用去管理资源??首先我们要明白当我们调用Resource.UnloadUnusedAssets,这个UnusedAssets代表什么意思??我们先了解被使用(used),不是被使用的就是Unused的了。下面是被视为使用的情况: 1)静态变量引用的资源,Monobehavior中变量/属性引用的资源被视为 2)被C#层强引用或被Lua简介引用的资源 因此,如果我们使用弱引用去管理资源,使用UnloadUnusedAssets就可以直接卸载我们不使用的资源,这样就无须再做一次引用计数的管理。 来源:UnloadUnusedAssets - what exactly does "unused" mean - Unity Answers ? # 最后?最后通过上面这张图了解下整个流程,我们先通过LZ4压缩了ab包,因此可以使用LoadFromFile只加载AB的Header到内存,在后续加载资源的时候,从AB缓存中读取资源,并用弱引用持有引用,方便后续再加载的时候,直接返回资源,就不去AB包中读取。在场景卸载后,先销毁游戏对象,然后调用Resources.UnloadUnusedAsset,弱引用中的Target失效,这时候清理弱引用。如此循环加载速度保证了,内存也维持到了一个比较好的水平。下一步需要优化就需要对于具体资源以及代码逻辑进行优化,就没有那么容易提升那么多效果了。下面放一张加载测试图,另外具体的修改代码后续会提交到git上,之后再补上。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/28 0:33:58- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |