首页 > 解决方案 > 为什么 C# 空条件运算符不适用于 Unity 可序列化变量?

问题描述

我注意到,如果我有一些变量暴露给 Unity 检查器,例如:

[SerializeField] GameObject _tickIcon;

如果我不分配它们并尝试使用 null 条件运算符并在该对象上调用一个方法,我会收到一个异常,指出该变量未分配。所以基本上不是这样做:

_tickIcon?.SetActive(false);

它迫使我这样做:

if(_tickIcon != null)
{
   _tickIcon.SetActive(false)
}

所以我猜这一定是unity运行时特有的东西,它不是真的为null,但我可以检查null并且它可以工作。我真的不明白这一点。

标签: c#unity3dserialization

解决方案


它通常不适用于继承自的任何东西UnityEngine.Object

由于它们在内部实现==/!=方法的方式不同,因此绕过了它。请参阅自定义 == 运算符,我们应该保留它吗?

ReSharper 在可能意外绕过底层 Unity 引擎对象的生命周期检查中解释得很好

如果派生自的类型UnityEngine.Object使用空合并 ( ??) 或空传播或条件 ( ?.) 运算符,则会显示此警告。这些运算符不使用在 上声明的自定义相等运算符UnityEngine.Object,因此绕过检查底层原生 Unity 引擎对象是否已被破坏。为了阐明意图,首选显式null或布尔比较或调用。System.Object.ReferenceEquals()

UnityEngine.Object在某些情况下并非如此 null,但仍保留一些元数据。所以底层object(= System.Object)不是null,UnityEngine.Object的覆盖==运算符只是返回truefor == null

_tickIcon?.gameObjct因此,像throw a这样的事情的主要原因NullReferenceException?.操作员只直接在底层工作,objectUnityEngine.Object他们的自定义实现在不同的级别上工作。

例如之后

Destroy(_tickIcon);
_tickIcon.SetActive(false);

你会注意到你没有得到一个正常NullReferenceException的情况,如果它实际上是这种情况,null而是让一个 Unity 习惯MissingReferenceException告诉你抛出异常的可能原因。


长话短说:由于解决方案UnityEngine.Object具有隐式bool运算符

对象存在吗?

那里给出的例子实际上并不是真的 - 见上文

您应该始终检查是否存在源自以下内容的任何内容UnityEngine.Object

if(_tickIcon)
{
    _tickIcon.SetActive(false);
}

推荐阅读