Unity: Null Check Not Working?

Ever checked an object for null and it didn’t work? Computers do precisely what you tell them to do -> it must be a programming error that bypasses the null check.


This is one of the moments where I doubt my sanity as a programmer.


What Happened?

The C# target object isn’t null but the C++ object it pointed to is. In my case, the target is a MonoBehaviour referenced as an interface. The != operator, therefore, executed a pure C# null check instead of Unity’s custom null check which leads to the null reference exception.




Unity is a bit special when it comes to null checks. Most of the Unity engine is built in C++. The properties of GameObjects and UnityEngine.Objects live in the C++ part of the engine. The C# object only contains a pointer to the native C++ object.


The problem with this separation is, that the lifetime of the C++ and C# objects can be different because of memory management. The C++ object can already be destroyed while the C# object is still waiting for the garbage collector. The C# object isn’t null and passes the C# null check. But accessing it will lead to a null reference exception in the C++ engine.


To handle this problem Unity overloaded the == operator to return null for the C# object when the C++ native object is null.


This has a few problems:


  • It’s slow
  • Not thread-safe
  • Inconsistent behaviour with the ?? operator which does a pure C# null check.  (Should never be used with UnityEngine.Objects because of the above reason.)
  • It does not work when the object is boxed or referenced as an interface



The problem is that the compiler executed a C# null check instead of a Unity null check. This behaviour can be fixed in two ways:

  1. Don’t reference a UnityEngine.Object as interface or box it
  2. Cast it to UnityEnigne.Object before doing the null check.
if ((target as UnityEngine.Object) != null)