Version: 1.4
语言 : 中文
运行时内存优化
IL2CPP 运行时内存优化

内存优化指引

减少 WASM 代码编译内存

小游戏平台简介 内存相关小节中,介绍到 WASM 代码对小游戏内存占用影响非常大。 编译和指令优化、JIT 优化消耗的总内存是 WASM 文件的10倍左右。

因此尽力优化代码大小,对减少小游戏的内存占用非常重要。用户可以参考Wasm代码精简章节进行优化。

资源内存优化

纹理资源优化

压缩纹理

纹理资源应使用 ASTC 格式压缩,从而大幅减少内存和 GPU 显存占用。对于过大的纹理,可以适当降低分辨率,其原则是保持纹理的分辨率和该纹理被使用时显示在设备屏幕上的分辨率基本一致。

在分辨率不变的情况下,提高压缩的等级,如从 ASTC6x6,调整为 ASTC8x8 甚至是 ASTC12x12,也可以大幅减少内存。例如近乎纯色的背景图,细节信息非常较少,使用 ASTC12x12 和 ASTC6x6 时,视觉上并没有明显区别,但内存占用却减少了3/4。

在同时调整分辨率和压缩等级时,应该优先保证分辨率。 即占用同样内存的情况下,高分辨率高压缩的贴图,比低分辨率低压缩等级的贴图,细节保留更完整。 例如一张贴图的原始分辨率为 2048x2048,应优先将其调整为 2048x2048,ASTC12x12,而不是 1024x1024,ASTC6x6。

同时 Compressor Quality 应该调整为 100,从而在相同的内存占用下获得更好的纹理质量。该选项会影响 Editor 压缩纹理时消耗的时间。

压缩后的纹理,在 AB 中占用的文件大小也会大幅减少,对减少 CDN 流量使用,改善游戏体验也很有帮助。

取消 Read/Write

对于未勾选 Read/Write 的贴图,引擎在将其上传到 GPU 后,便会释放内存中占用的纹理数据。而勾选了 Read/Write 的纹理,数据则会一直在内存中,导致纹理内存占用翻倍。因此对于所有不需要读写的纹理,都应该取消 Read/Write 的勾选。

取消 Generate Mip Maps

小游戏平台不支持 Texture Streaming 功能,因此 Mip Map 只有在 3D 物体的渲染效果改善上有用,无法减少 GPU 显存占用。对于 UI 和 CubeMap 之类的贴图,应该取消勾选 Generate Mip Maps,从而减少1/3的内存占用。

音频资源优化

AudioClip 在解压时,会在 JS 层占用大量的内存,因此音频的加载类型应该选择 Compressed Included Memory。另外强制使用单通道音频,也能在音频播放时节省一半的内存消耗。

大多数情况下,导入音频的 Quality 选择1和100,在听觉上并没有什么区别,而音频数据却能大幅减小,因此推荐小游戏平台,将所有音频的 Quality 都调整为1。

总结而言,音频资源的内存优化方式有:

  • 加载方式使用 Compressed In Memory

  • 勾选 Force To Mono,强制使用单声道音频

  • Quality 调整为1

注:在普通浏览器中使用时,由于安全保护问题,请勿使用压缩音频,否则可能导致声音播放不正常。

模型资源优化

取消 Read/Write

对于未勾选 Read/Write 的模型,上传到 GPU 后,便会释放内存中占用vertex和index buffer。而勾选了。而勾选了 Read/Write 的模型,数据则会一直在内存中,导致内存占用翻倍。因此对于所有不需要读写的模型,都应该取消 Read/Write 的勾选。

降低内存峰值

小游戏平台上,Mono Heap 由 Il2cpp 分配管理,其他 Native 内存(包括引擎 Native Heap 和其他第三方库如 Lua )由 Emscripten 的 malloc 分配管理(默认使用 dlmalloc )。 这两部分都是只增不减,而且相互独立,空闲空间无法共享,因此需要各自都注意控制峰值。

Mono Heap 峰值的一个典型来源是游戏配置的加载,Native Heap 的峰值通常出现在大量 AssetBundle 加载时。且小游戏平台上因为单线程原因,在单帧内无法执行 GC 操作,因此需要注意单帧的内存分配。

使用团结引擎

团结引擎对小游戏运行时做了很多内存的优化。同时提供的 AutoStreaming 功能也能避免加载部分未使用的资源,因此使用团结引擎能够对降低内存占用起到帮助。

其他优化

释放 AssetBundle 及 AB文件

由于小游戏平台无法使用文件系统,加载 AssetBundle 时往往会带来AB文件大小2–3倍的内存开销。因此在使用完AB之后及时释放对减少内存消耗也很重要。

另外,在下载AB文件时,应尽量避免使用 UnityWebRequest 的 cache 机制,cache 下来的文件会通过 Emscripten 存在JS内存文件系统中,并且没有方法可以主动删除。

对于主动调用文件IO接口、写入JS内存文件系统中的AB文件,在使用完成后,也应该主动删除,从而释放AB文件占用的内存。

关闭 GraphicsSetting 中的 HDR

如果小游戏使用的是 built-in 管线,并且未使用到 HDR,请前往 Graphics Setting 中的 tier2(小游戏平台使用 tier2 中的设置)关闭默认开启的 hdr,可以节省约40MB的显存开销,并且少了一次 RT 的拷贝操作。

避免冗余的资源

游戏加载过程中,可能会有冗余的资源长期占用内存。冗余资源主要来源以下两方面:

  • 不合理的AB打包机制,导致 Shader,Font 等资源在不同的AB内重复存在。对于这一情况,需要通过 AssetStudio 等工具发现冗余的资源,调整AB打包的结构来避免。

  • 加载游戏配置的中间产物长时间存在内存当中。例如游戏将配置文本文件打包到了AB中。启动游戏时,从AB中加载了一个 TextAsset,然后从 TextAsset 中获取了整个文件的长字符串,并将字符串处理成字典等数据结构。

只有最终的字典数据是真实被使用的,而在此之前的加载的 AB,TextAsset 和长字符串如果未释放,也将在内存中占用不少的内存。小游戏平台支持 MemoryProfiler package,因此可以打包 development 版本并开启 Autoconnect Profiler,在游戏启动并连接到 Editor 后,使用 MemoryProfiler 抓取内存帧,分析内存冗余情况。

运行时内存优化
IL2CPP 运行时内存优化