Unity C#布尔OR语句一侧为真时整体仍返回false问题求解
问题原因
- 本质是C#运算符重载静态绑定机制和Unity自定义null逻辑的冲突:
- Unity只在
UnityEngine.Object基类(所有GameObject、组件、脚本资源的父类)上重载了==/!=运算符,实现“对象调用Destroy后与null比较返回true”的特殊规则。实际上被销毁对象的托管堆实例并未立即回收,只是引擎侧原生对象已被释放。 - 你的
buildable变量是IBuildable接口类型,编译器编译接口类型的==比较时,无法确认实例一定继承自UnityEngine.Object,因此不会绑定Unity重写的运算符,只会执行原生引用相等判断。这种场景下被销毁的对象不是真null,buildable == null实际运行返回false,不会触发||的短路逻辑。
- Unity只在
- 调试窗口显示结果和实际运行不符是IDE调试器的特殊处理导致:Rider、VS等工具的调试器识别到Unity对象实例时,会自动套用Unity的null规则计算表达式,因此你看到监视窗口里
buildable == null为true、完整条件返回true,但这和最终编译执行的IL逻辑不一致。 - 后续执行
buildable.BuildingComplete时,访问已销毁的Unity对象成员会触发引擎的缺失引用处理,返回false,最终导致整个属性返回结果不符合预期。
修复方案
禁止直接对接口类型变量使用==null判断Unity对象的销毁状态,先将其转换为UnityEngine.Object类型再执行Unity规则下的空判断,参考代码如下:
public override bool IsFinished { get { if (buildable is UnityEngine.Object unityObj) { // 确认是Unity引擎对象,走自定义空判断 if (unityObj == null) return true; return buildable.BuildingComplete; } // 非Unity对象执行常规空判断 return buildable == null || buildable.BuildingComplete; } }
如果IBuildable的所有实现类都确定继承自UnityEngine.Object,可以直接简化为:
public override bool IsFinished { get { return (buildable as UnityEngine.Object) == null || buildable.BuildingComplete; } }
最佳实践:可以封装一个Unity对象的通用扩展方法做判空,统一处理接口、泛型类型的空判断场景,避免同类运算符绑定错误。
内容的提问来源于stack exchange,提问作者miroki
相关产品推荐
相关产品推荐

