来源摘要: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。