IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: 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即可

BuildAssetBundleOptions buildOption = BuildAssetBundleOptions.IgnoreTypeTreeChanges | BuildAssetBundleOptions.DeterministicAssetBundle | BuildAssetBundleOptions.ChunkBasedCompression;

## 修改AB包读取方式

//读取ab包
AssetBundle.LoadFromFileAsync(url)

这里需要注意一点的就是,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上,之后再补上。

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-11-12 19:55:20  更:2021-11-12 19:56:43 
 
开发: 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-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码