我一直得到这个异常: "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);
我的问题是,我怎么可能得到一个空引用,即使对象有一个刚体(每个抛出这个异常的对象在错误发生时仍然有它的刚体活动和连接)。
先谢谢你,祝你有一个愉快的一天。
你不应该使用 ?
或 ??
继承自 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
),它应该是一个方法。但也许这只是一个品味问题。