Unity接入Crashlytics时如何定位空引用异常的具体对象及行号
1. 上传调试符号补全堆栈行号
你当前看不到行号的核心原因是Unity IL2CPP打包时默认剥离了调试映射信息,配合Crashlytics的符号上传能力可以直接还原行号,不需要额外埋点:
- 安卓端:在Build Settings中将「剥离调试信息」设置为仅剥离非用户代码,打包时将生成的
.sym符号文件、IL2CPP的行号映射文件同步上传到Crashlytics后台,即可将原生堆栈的偏移量转换为C#代码行号。 - iOS端:打包时不要勾选「Strip Debug Symbols During Copy」,将打包生成的dSYM文件上传到Crashlytics,即可还原完整C#堆栈行号。
2. 用日志面包屑替代逐行自定义Key
相比逐行调用Crashlytics.SetCustomKey()会覆盖旧值的问题,用Crashlytics.Log()上报操作节点效率更高,崩溃上报时会自动携带崩溃前的全量日志:
- 仅需要在报错的
MoveSuggestionTouched、MakeNextMoveByBot两个方法的关键操作节点打日志即可,比如「进入AI落子逻辑」、「获取当前棋盘实例」、「读取移动提示对象」、「调用触摸回调」,崩溃后查看最后一条日志即可定位到异常发生的步骤。 - 可以给每个异步任务加上唯一ID,日志中携带任务ID,即可明确是哪一次AI异步任务触发的异常。
3. 精准定位被销毁的Unity对象
针对Unity特有的对象已销毁但变量不为null的场景,可以仅对核心访问对象加轻量埋点:
- 对棋盘、对局控制器、移动提示对象这类可能被异步逻辑访问的实例,在
OnDestroy()生命周期中上报日志[对象类型] 已销毁,实例ID:{实例ID},如果崩溃日志中存在对应对象的销毁记录,即可直接确认空引用来源。 - 可以封装统一的轻量检查扩展方法,不需要全量加空检查,仅在异步逻辑访问核心对象前调用即可:
public static bool CheckValid(this UnityEngine.Object obj, string tag) { if (obj == null) { Crashlytics.Log($"对象无效:{tag} 已为空/已销毁"); return false; } return true; }
崩溃时通过日志即可直接确认是哪个对象为空。
4. 优化异步方法堆栈可读性
你当前的堆栈是C#异步方法编译后的状态机堆栈,缺少上下文,在Player Settings中将「异常支持」设置为完整,关闭代码混淆的激进裁剪选项,即可让异步方法的堆栈保留更多执行上下文信息,更容易定位具体执行步骤。
内容的提问来源于stack exchange,提问作者Paiman Roointan
相关产品推荐
相关产品推荐

