How am I misusing the null-coalescing operator? Is this evaluating “null” correctly?

This is Unity screwing with you.

If you do this:

MeshFilter GetMeshFilter()
{
    MeshFilter temp = myGo.GetComponent<MeshFilter>();

    if ( temp == null ) {
        Debug.Log( "    > Get Mesh Filter RETURNING NULL" );
        return null;
    }
    return temp;
}

It works.

Why?

Because Unity has overridden Equals (and the == operator) on all Unity objects so that destroyed game objects and never existing objects are both “equal” to null (this was done in an attempt to make developer’s lives easier). But a destroyed (or “missing”) object is not literally null: its a wrapper object in the C# part of the engine pointing at a null object in the underlying C++ code. The null coalescing operator checks for literally null.

For example try this:

Start() {
    GameObject gg = new GameObject(); //create a GO
    DestroyImmediate(gg); //destroy it immediately
    Debug.Log(gg == null); //prints true: it is definitely null!
    GameObject go = gg ?? this.gameObject; //get a non-null object
    Debug.Log(go); //prints null
}

This is also why you get a MissingReferenceException when you try to access Unity objects that are null, rather than a NullReferenceException: those objects aren’t literally null, but only effectively null.


In general that’s what the Object.bool operator is used for. Just prefer to use it instead of a null check:

public static T GetComponentOrAddIfMissing<T>(this GameObject self) where T : Component
{
    T component = self.GetComponent<T>();

    if(!component) component = self.AddComponent<T>();

    return component;
}

Leave a Comment