解决 Unity 游戏中的 ANR 问题是一个系统化的流程:

集成报告服务
Android Vitals、Firebase Crashlytics 和 Backtrace(经过认证的 Unity 合作伙伴)等报告服务可大规模为您的游戏提供错误日志记录和分析。在开发周期的早期阶段,将报告服务 SDK 集成到游戏中。分析哪种报告服务最符合您的游戏需求和预算。
不同的报告服务捕获 ANR 的方式不同。添加第二个报告服务,以提高获得有效数据的几率,从而支持您在修复 ANR 时做出的决策。
集成报告 SDK 不会影响游戏性能或 APK 大小。
分析符号
分析报告服务中的报告,并检查堆栈轨迹是否采用人类可读的格式。如需了解详情,请参阅对 Unity 游戏的 Android 崩溃和 ANR 问题进行符号化解析。

libil2cpp.so
符号。如何查看符号 build ID
如果报告系统显示 build ID 缺失,但 build 符号仍存在于 build 机器存储空间中,则可以检查符号的 build ID,然后将其上传到报告服务。否则,您需要新建 build 才能上传符号文件。
在 Windows 或 macOS 上:
- 根据您的脚本后端导航到符号文件夹(请参阅解决方案):
- 使用以下命令(在 Windows 上,使用 Cygwin 运行
readelf
实用程序) - grep 用法是可选的,可用于过滤文本输出
- 查找 build 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 或其他报告服务的历史记录,并检查游戏发生错误最多的发布版本。查看版本控制历史记录中的源代码,并比较不同版本之间的代码更改。如果您发现可疑情况,请单独尝试每项更改或潜在的修复。
- 检查收到最多 ANR 的设备和 Android 版本的 Google Play ANR 报告历史记录。如果设备或版本已过时,那么如果忽略它们不会影响游戏的盈利能力,您很可能可以放心地忽略它们。请仔细研究数据,因为特定用户群将无法再玩您的游戏。如需了解详情,请参阅“分布”信息中心。
- 检查游戏源代码,确保您没有调用任何可能导致问题的代码,例如,如果使用不当,finish 可能会造成破坏性影响。如需详细了解 Android 开发,请参阅 Android 开发者指南。
- 查看数据并将游戏 build 导出到 Android Studio 后,您将处理 C 和 C++ 代码,因此可以充分利用 Unity 标准解决方案之外的工具,例如 Android 内存分析器、Android CPU 分析器和 perfetto。
Unity 引擎代码
如需了解 Unity 引擎端是否发生了 ANR,请检查堆栈轨迹中是否存在 libUnity.so
或 libMain.so
。如果您发现这些文件,请执行以下步骤:
- 首先,搜索社区渠道(Unity 论坛、Unity 讨论、Stackoverflow)。
- 如果您未找到任何内容,请提交 bug 以解决问题。提供符号化堆栈轨迹,以便引擎的工程师更好地了解和解决错误。
- 检查最新的 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
;不过,您自己的实现可让您更精细地控制,并能够包含更相关的信息。