Destroyed object not comparing to null

I read that once a GameObject is destroyed, comparing it to null will return true. But I have this line of code which yields a MissingReferenceException saying the object has been destroyed but I’m still trying to access it:

if (shootTarget != null) {
    // something
} else {
    distance = shootTarget.GetDistance(this.transform.position);
}

Any ideas why? Any other checks I can perform?

Update:

Ok I found the reason, but not a solution. shootTarget is not a MonoBehaviour per se, it’s an interface I created, but the MonoBehaviour implements the interface and the actual value of shootTarget is a MonoBehaviour that’s been destroyed, so comparing it to null doesn’t yield true…

Any ideas how to work around this?

Inspired by @tbkn own answer, I did a bit of research. MonoBehaviour == operator is not overriden - it’s Object == operator. But I see that Equals method is overriden as well, so you might try

object.Equals(shootTarget, null)         // C#
System.Object.Equals(shootTarget, null)  // JS

If code from your answer works, this should work as well.

EDIT: after a bunch of additional test it looks like the correct solution is the one posted by tbkn in a comment below:

shootTarget == null || shootTarget.Equals(null)

The first condition prevents situation when the shootTarget really becomes null, while second one correctly uses Equals overriden in UnityEngine.Object.

Ok, figured out a possible solution, though not the most elegant. Will keep this question open a bit more to see if anyone knows a more elegant solution.

Apparently a MonoBehaviour’s operator == is overridden to return true when comparing a destroyed object to null. Apparently, in C#, when you override an operator of a class, it will not match the overridden operator when you compare an instance of that class that is assigned to an interface variable. This is to do with the fact that operator resolution is done in compile time, and not runtime like virtual methods.

MonoBehaviour myMono;
MonoBehaviourInterface myMonoInterface = myMono;

// this will use the overloaded operator== of MonoBehaviour
if (myMono == null) {}

// this will NOT use the overloaded operator== of MonoBehaviour
if (myMonoInterface == null) {}

Thread in which this is discussed: .net - Operator Overloading with Interface-Based Programming in C# - Stack Overflow

So my solution would be to cast shootTarget to MonoBehaviour when doing the comparison to null. Although I don’t know the exact class of shootTarget, I do know it is a subclass of MonoBehaviour, so this works.

if (((MonoBehaviour)shootTarget) == null) {
    // something
} else {
    distance = shootTarget.GetDistance(this.transform.position);
}

Since the interface doesn’t know about the original MonoBehaviour’s operators, you won’t get the over-ridden behaviour of operator == (from UnityEngine.Object), which is where destroyed objects are “equal” to null.

The following test will work for interface implementations that may or may not be MonoBehaviours.

if ((shootTarget == null) || ((shootTarget as UnityEngine.Object) == null)) {
    // something
} else {
    // something else
}

The first check handles the general case of the object actually being null. The second check handles the case of a destroyed Unity object.

I have had this issue in the past. Calling destroy on a monobehaviour will not destroy it instantly however it will mark it as destroyed. When you destroy the object also set it to null to be extra safe.

E.G

Destroy( shootTarget );
shootTarget = null;

Edit:

I assume that shootTarget is some property of an other script in which case you are fine to set it to null from an external script. Its still the same variable.

The fixes above didn’t work for me, but it’s possible that some of these stopped working during the 5.x era. Here’s a workaround that I found:

Equals(obj, "null")