在将Unity App 游戏移植到微信小游戏的过程中,很多团队都会遇到一个非常典型的问题:Android 运行稳定,但 iOS 经常闪退。
经过大量项目经验和测试数据分析,我们发现:大多数闪退问题,其实都与小游戏的内存结构有关。而微信小游戏的内存机制,与传统 Unity App差异非常大。
本文将通过大量实测数据,系统拆解:
微信小游戏的内存结构
不同资源类型的内存表现
为什么 iOS 会在 1.3GB 左右闪退
如何通过资源管理减少闪退风险
1
微信小游戏的内存结构
在微信官方文档中,有一张小游戏内存结构图。
但很多开发者第一次看到这张图时都会有一个感觉:看不太懂。因为小游戏的内存结构,与 Unity App 的内存结构差异很大。
官方文档中有一句非常关键的说明:Mono Heap + Native Reserved + 原生插件内存 = Dynamic Memory
其中最容易产生误解的是:Native Reserved,很多开发者会把它理解为 Unity App 中的:
Native Memory
Unity Reserved Memory
但实际上,两者并不完全一致。为了搞清楚真实情况,我们做了大量测试,分别分析了不同资源类型:
AssetBundle
Texture
Mesh
通过这些测试,我们逐渐还原了小游戏内存的真实行为。
2
iOS 为什么在 1.3GB 左右闪退?
当我们用Xcode 调试微信小游戏时,会看到两个核心进程:WeChat 进程以及WebKit.WebContent 进程,为了方便理解,我们把它们称为:
WeChat 进程
Web 进程
经过测试发现:小游戏的闪退几乎全部发生在 Web 进程。当 Web 进程的内存超过约1.3GB,系统就会触发崩溃。
我们做了一个压力测试,测试数据:
图片数量:100 张
单张大小:21.3MB
分辨率:2048 × 2048
未压缩
开启 Read / Write
然后将这些图片打包成AssetBundle并逐个加载。结果如下:
WeChat 进程:增长约 2.1GB
Web 进程:增长较少
这说明一个关键问题:纹理资源的内存大部分进入了 WeChat 进程。
因此:仅仅加载纹理资源,通常不会导致小游戏闪退。小游戏闪退真正的原因是:Web 进程内存超过限制。
3
AssetBundle 对内存的影响
接下来我们测试AssetBundle 的加载行为。
测试数据:
AssetBundle 数量:21 个
总体积:约 200MB
首先使用Unity 原生接口加载。
加载后的内存变化:
Native Reserved 增加约200MB,Dynamic Memory增加约200MB;
Web 进程同步增长,WeChat 进程几乎没有变化。
这说明:AssetBundle 主要影响 Web 进程内存。而 Web 进程正是iOS 闪退的关键限制。
因此我们建议:尽量使用微信官方提供的 AB 加载接口。
原因包括:
支持及时卸载
自带缓存管理
更适合小游戏环境
4
一个常被忽略的问题:AB 利用率
在分析项目资源时,我们发现一个非常常见的问题:很多 AssetBundle 的利用率非常低。
有些 AB 的资源利用率甚至低于 10%。换句话说:90% 的资源被加载,但从未使用。为了解决这个问题,我们开发了一个工具,用来统计:
AB 中资源数量
实际被使用的资源数量
统计方式是通过分析:RefCount(引用计数),从而区分:
主动加载资源
被动引用资源
最终计算:资源利用率 = 实际使用资源 / AB 内资源,对于利用率极低的 AB,我们会进一步分析:哪些资源体积最大?为什么被加载却没有使用?优先处理“体积大但利用率低”的资源。
本文内容节选自我们的课程《从App到多平台小游戏 - 高效迁移的全链路优化策略》,更多关于各类资源(纹理 / Mesh / 动画 / 音频)的内存行为,“同步转异步”的问题,iOS的异常处理以及我们在一些在项目中实际做过的性能优化点分享,可复制 链接浏览器打开/点击文末【阅读原文】了解课程详情:
https://edu.uwa4d.com/course-intro/0/629
热门跟贴