来源摘要:Entity 异步安全与空引用防护

摘要

记录一次针对 Unity 游戏代码中 NRE(空引用异常)的修复实践:报错堆栈显示异常出现在实体的异步流程之后(实体可能已被回收/隐藏),根因是代码在 await/延迟回调中仍直接访问 Entity 或 Entity.Id。素材给出了解决策略、已做的修复、后续可执行方案与补丁模板。

要点

  • 根因:实体异步流程后(await/延迟/回调中)直接访问 Entity 或 Entity.Id,而此时父对象可能已被回收或隐藏。
  • 解决策略:
    • 立即使用 Entity.Id 处先判空(Entity != null)。
    • 延迟回调中先捕获 Entity.Id(int)到局部变量,回调内只使用该 id,不直接访问 Entity 引用。
    • 解析目标实体 id(如 homing 子弹)时做防御性 null 检查,无法解析时用 0 表示”无目标”。
  • 已处理:在文件中应用最小改动补丁,仅在必要处增加判空或捕获 id,编译通过。
  • 后续可选项:全仓库自动扫描修补、HideEntity 统一为 id 版本、为实体基类增加 TryHideSelf/SafeHide 便捷方法、为延迟/异步回调建立规范、复杂 await 处加注释。

补丁模板(要点)

  • 延迟闭包:DOVirtual.DelayedCall(dt, () => ...) 内访问 Entity 的,改为先 var cap = Entity != null ? Entity.Id : 0;,回调内判断 cap != 0 再按 id 操作。
  • await 后访问:先判空再取 id,if (Entity == null) return; var id = Entity.Id; await SomeAsync(); 后续用 id。

关联概念/实体

来源