首页 > 解决方案 > 缺少刚体字段的引用异常和?? 操作员

问题描述

我不断收到此异常:“MissingReferenceException:'Rigidbody' 类型的对象已被破坏,但您仍在尝试访问它。”

它的问题是我只能通过这个字段来访问它:

    private Rigidbody m_Rigidbody = null;
    private Rigidbody Rigidbody => m_Rigidbody ?? (m_Rigidbody = GetComponent<Rigidbody>());

我的异常在这一行被抛出:

    public float CurrentSpeed => (Rigidbody?.velocity.magnitude ?? 0f) * ((m_SpeedType == SpeedType.MPH)?2.23693629f : 3.6f);

我的问题是,我怎么可能得到一个空引用,即使对象有一个刚体(如果发生错误,每个抛出这个异常的对象仍然有它的刚体活动并附加)。

提前致谢,祝您有美好的一天。

标签: c#unity3dnullreferenceexceptionrigid-bodies

解决方案


你不应该使用???继承自UnityEngine.ObjectATALL 的任何东西。

它在某种程度上与 Unity 如何在内部实现它们的==和操作符有关(这基本上是任何组件、游戏对象、资产等的超类)!=UnityEngine.Object

另请参阅可能意外绕过底层 Unity 引擎对象的生命周期检查,其中 Re-Sharper Plug-In for Unity 的制造商根据UnityBlog 进一步解释了它 - “自定义 == 运算符,我们应该保留它吗?”

检查==nulland 因此也,特别是使用?and??运算符被简单地绕过UnityObject

为什么?

从表面上看:在调用之后Destroy(或者例如,如果它是一个序列化的字段并且尚未被引用)Object Unity 中的 an 不再存在。不是真的==null,它仍然保存一些元数据,而且只是-他们如何陈述它

一个fake null object

这实际上是您没有得到 a 的原因,NullReferenceException但 Unity 内置MissingReferenceException提示您为什么通常会NullReferenceException在这一点上得到 a。它可以例如状态

'XY' 类型的对象已被破坏,但您仍在尝试访问它


然而,特别是由于这个原因UnityEngine.Object,有一个隐式bool运算符返回

对象存在吗?

因此,例如if(destroyedObject)afterdetroyedObject已被调用Destroy(destroyedObject);,或者它是一个从未分配过的字段,但现在将不会被执行(不再),因为它是 now false


所以你想要做的特别是对于被Destroy编辑的东西实际上是使用那个操作符,比如

private Rigidbody m_Rigidbody = null;
private Rigidbody Rigidbody
{
    get
    {
        if(m_Rigidbody) return m_Rigidbody;

        m_Rigidbody = GetComponent<Rigidbody>();

        return m_Rigidbody;
    }
}

出于可读性的原因,无论如何我都不喜欢将这样的东西制作成一个表达式体。

您的其他财产也将相应地

public float CurrentSpeed => Rigidbody ? Rigidbody.velocity.magnitude * ((m_SpeedType == SpeedType.MPH) ? 2.23693629f : 3.6f) : 0f;

一般来说,我的意见是:每当一个属性中可能隐藏更多工作时,那么只简化引用(如这里 eg GetComponent)它应该是一种方法。但也许这只是口味问题。


推荐阅读