解决 Unity 游戏中的应用无响应 (ANR) 问题是一个系统性过程

集成报告服务
Android vitals、Firebase Crashlytics 和 Backtrace(一个经过认证的 Unity 合作伙伴)等报告服务可以大规模地为您的游戏提供错误日志记录和分析。在开发周期的早期将报告服务 SDK 集成到您的游戏中。分析哪种报告服务最符合您的游戏需求和预算。
不同的报告服务有不同的捕获 ANR 的方式。包含第二个报告服务以增加获取有效数据的机会,从而支持您修复 ANR 的决策。
集成报告 SDK 不会影响游戏性能或 APK 大小。
分析符号
分析报告服务中的报告,并检查堆栈跟踪是否为人类可读格式。如需了解详情,请参阅符号化处理 Unity 游戏的 Android 崩溃和 ANR。

libil2cpp.so
符号。如何检查符号构建 ID
如果报告系统显示构建 ID 缺失,但构建符号仍然存在于构建机器存储中,则可以检查符号的构建 ID,然后将其上传到报告服务。否则,需要新的构建才能上传符号文件。
在 Windows 或 macOS 上
- 根据您的脚本后端导航到符号文件夹(请参阅解决方法:)
- 使用以下命令(在 Windows 上,使用Cygwin 运行
readelf
实用程序) - Grep 用法是可选的,用于过滤文本输出
- 查找构建 ID
- 使用以下命令(在 Windows 上,使用Cygwin 运行
readelf -n libil2cpp.so | grep 'Build ID'
Build ID: b42473fb7449e44e0182dd1f580c99bab0cd8a95
检查游戏代码
当堆栈跟踪显示 libil2cpp.so
库中的函数时,错误发生在 C# 代码中,该代码已转换为 C++。libil2cpp.so
库不仅包含您的游戏代码,还包含插件和软件包。
C++ 文件名遵循 Unity 项目中定义的汇编名称。否则,文件名具有默认的 Assembly-C# 名称。例如,图 3 显示文件 Game.cpp
(蓝色突出显示)中的错误,这是在汇编定义文件中定义的名称。Logger
是 C# 脚本中的类名(红色突出显示),后跟函数名(绿色突出显示)。最后是 IL2CPP 转换器生成的完整名称(橙色突出显示)。

通过执行以下操作检查您的游戏代码
- 检查 C# 项目中是否有任何可疑代码。通常,C# 未处理的异常不会导致 ANR 或应用程序崩溃。即便如此,请确保代码在不同情况下都能正常运行。检查代码是否使用了第三方引擎模块,并分析最近的版本是否引入了错误。此外,请检查您最近是否更新了 Unity,或者错误是否只发生在特定设备上。
- 将游戏导出为 Android Studio 项目。通过完全访问游戏转换后的 C# 源代码,您可以找到导致 ANR 的函数。C++ 代码与您的 C# 代码看起来非常不同,并且代码转换很少出现问题。如果您确实发现了问题,请向 Unity 提交支持工单。
- 查看游戏源代码,确保在 OnApplicationFocus() 和 OnApplicationPause() 回调中运行的任何逻辑都已正确清理。
- Unity 引擎有暂停执行的超时时间;这些回调上的过度工作可能会导致 ANR。
- 在代码的某些部分添加日志或面包屑,以增强您的数据分析。
- 使用 Unity Profiler 来调查游戏的性能。分析您的应用也是识别可能导致 ANR 的瓶颈的好方法。
- 识别主线程上长时间 I/O 操作的好方法是使用严格模式。
- 分析 Android Vitals 或其他报告服务的历史记录,并检查错误发生最多的游戏发布版本。在版本控制历史记录中查看您的源代码,并比较版本之间的代码更改。如果您发现可疑内容,请单独试验每个更改或潜在修复。
- 检查 Google Play ANR 报告历史记录中接收 ANR 最多的设备和 Android 版本。如果设备或版本过时,如果这样做不影响游戏的盈利能力,您很可能可以安全地忽略它们。仔细研究数据,因为特定的用户群将无法再玩您的游戏。如需了解详情,请参阅分发信息中心。
- 查看游戏源代码,确保您没有调用任何可能导致问题的代码,例如,如果使用不当,finish 可能会具有破坏性。请参阅 Android 开发者指南以了解有关 Android 开发的更多信息。
- 在查看数据并将游戏构建导出到 Android Studio 后,您将处理 C 和 C++ 代码,因此可以充分利用 Unity 标准解决方案之外的工具,例如 Android 内存分析器、Android CPU 分析器和 perfetto。
Unity 引擎代码
要了解 ANR 是否发生在 Unity 引擎端,请检查堆栈跟踪中的 libUnity.so
或 libMain.so
。如果找到它们,请执行以下步骤
- 首先,搜索社区频道(Unity 论坛、Unity 讨论、Stackoverflow)。
- 如果您没有找到任何内容,请提交错误以解决问题。提供符号化堆栈跟踪,以便引擎工程师能更好地理解和解决错误。
- 检查最新的 Unity LTS 是否对您的问题进行了改进。如果是,请将您的游戏升级到该版本。(此解决方案可能只适用于部分开发者。)
- 如果您的代码使用了自定义的
Activity
而不是默认的,请查看 Java 代码以确保该 activity 没有引起任何问题。
第三方 SDK
- 检查所有第三方库是否都是最新版本,并且没有针对最新版 Android 的崩溃或 ANR 报告。
- 前往 Unity 论坛,查看是否有任何错误已在更高版本中得到解决,或者 Unity 或社区成员是否提供了解决方法。
- 查看 Google Play ANR 报告,并确保 Google 尚未发现此错误。Google 已发现一些 ANR,并正在积极努力修复它们。
系统库
系统库通常超出开发者的控制范围,但它们在 ANR 中所占的比例不高。除了联系库开发者或添加日志以缩小问题范围外,系统库 ANR 很难解决。
退出原因
ApplicationExitInfo
是一个用于了解 ANR 原因的 Android API。如果您的游戏使用的是 Unity 6 或更高版本,您可以直接调用 ApplicationExitInfo
。对于较旧的 Unity 版本,您需要实现自己的插件以启用从 Unity 调用 ApplicationExitInfo
。
Crashlytics 也使用 ApplicationExitInfo
;然而,您自己的实现为您提供了更精细的控制,并使您能够包含更多相关信息。