在Rigidbody字段和?操作者的情况下,缺少参考异常。

问题描述 投票:0回答:1

我一直得到这个异常: "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# unity3d nullreferenceexception rigid-bodies
1个回答
1
投票

你不应该使用 ??? 继承自 UnityEngine.Object 根本就没有。

这与Unity如何实现他们的 ==!= 运营商内部为 UnityEngine.Object 基本上是任何Component、GameObject、Asset等的超级类)。

另见 可能无意中绕过了底层Unity引擎对象的寿命检查。 在这里,Re-Sharper插件的制作者为Unity进一步解释了它基于 UnityBlog - "自定义==运算符,我们应该保留它吗?"

检查 ==null 从而也和特别是使用 ??? 运营商只是 旁路UnityObject.

为什么这么说?

在表面上。呼叫之后 Destroy (或者,例如,如果它是一个序列化字段,并且尚未被引用)一个 Object 在Unity不存在了。但是 真的 ==null确切地说,它仍然保存着一些元数据,只是--他们是怎么说的。

a fake null object.

这实际上是为什么你没有得到一个原因。NullReferenceException 但Unity内置的 MissingReferenceException 给你个提示 何以 你通常会得到一个 NullReferenceException 在这一点上。例如,它可以说明:

类型为'XY'的对象已被销毁,但你仍在试图访问它。


然而,特别是由于这个原因 UnityEngine.Object 有一个隐性 bool 经营者 回归

该对象是否存在?

所以例如 if(destroyedObject)detroyedObject 被称为 Destroy(destroyedObject); 或者它是一个从未分配过的字段,但现在将不会被执行(不再),因为它现在是 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;

总的来说,这是我的观点。每当一个属性中可能隐藏着更多的工作,而不是仅仅简化引用时(比如这里的... GetComponent),它应该是一个方法。但也许这只是一个品味问题。

© www.soinside.com 2019 - 2024. All rights reserved.