I keep getting this exception: "MissingReferenceException: The object of type 'Rigidbody' has been destroyed but you are still trying to access it."
The problem with it is that i only accsess it by this field:
private Rigidbody m_Rigidbody = null;
private Rigidbody Rigidbody => m_Rigidbody ?? (m_Rigidbody = GetComponent<Rigidbody>());
and my exception is thrown at this line:
public float CurrentSpeed => (Rigidbody?.velocity.magnitude ?? 0f) * ((m_SpeedType == SpeedType.MPH)?2.23693629f : 3.6f);
What my question is, how is it possible that i get a null reference, even if the object has a rigidbody (every object that throws this exception still has its rigidbody active and attached if the error occures).
Thanks in advance and have a nice day.
You shouldn't use ?
or ??
on anything inheriting from UnityEngine.Object
AT ALL.
It is somehow related to how Unity implemented their ==
and !=
operators internally for UnityEngine.Object
(which is basically the super class for any Component, GameObject, Asset etc)
See also Possible unintended bypass of lifetime check of underlying Unity engine object where the makers of the Re-Sharper Plug-In for Unity explained it further based on UnityBlog - "Custom == operator, should we keep it?"
Checking for ==null
and thereby also and in particular using the ?
and ??
operators is simply bypassed by UnityObject
.
Why?
On the surface: After calling Destroy
(or eg if it is a serialized field and not referenced yet) an Object
in Unity does not exist anymore. BUT it is not really ==null
, it rather still holds some meta data and is only - how they state it
a
fake null object
.
That's actually the reason why you do not get a NullReferenceException
but the Unity built-in MissingReferenceException
giving you a hint why you usually would get a NullReferenceException
at this point. It could eg state
The object of type 'XY' was destroyed but you are still trying to access it
However in particular for this reason UnityEngine.Object
has an implicit bool
operator returning
Does the object exist?
so eg if(destroyedObject)
after detroyedObject
has been called Destroy(destroyedObject);
or it is is a field that was never assigned yet will now not be executed (anymore) since it is now false
.
So what you want to do especially for stuff being Destroy
ed would be actually using that operator like
private Rigidbody m_Rigidbody = null;
private Rigidbody Rigidbody
{
get
{
if(m_Rigidbody) return m_Rigidbody;
m_Rigidbody = GetComponent<Rigidbody>();
return m_Rigidbody;
}
}
For readability reasons I'm not a fan of making things like this an expression body anyway.
Your other property would then accordingly also be
public float CurrentSpeed => Rigidbody ? Rigidbody.velocity.magnitude * ((m_SpeedType == SpeedType.MPH) ? 2.23693629f : 3.6f) : 0f;
In general any my opinion: Whenever there might be more work hidden inside a property then only simplifying references (like here eg GetComponent
) it should rather be a method. But maybe this is just a matter of taste.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.