Simple question about null conditional operator

Hello
About the the null conditional operator:

I have 2 lines of code, the second one producing an exception

print("1" + GameObject.Find("notExistent")?.gameObject);
print("2" + GameObject.Find("GameManager")?.GetComponent<CircleCollider2D>()?.radius);

My GM doesnt have a CircleCollider2D, but why can I use ? on the GameObject-method and not on GetComponent??

I imagine it’s because radius isn’t a nullable type.

no, I can also write .gameObject
btw the exception is

You probably need to add a CircleCollider2D to the game object "GameManager". Or your script needs to check if the component is attached before using it.```

That’s because GetComponent() is the Generic Function for (CircleCollider2D) go.GetComponent(typeof(CircleCollider2D)).

Null conditioner operator gives exception when you trying to typecast the null variable.

Try using:

print("2" + GameObject.Find("GameManager")?.GetComponent(typeof(CircleCollider2D))?.GetComponent<CircleCollider2D>().radius);

This is a common stumbling block when getting into Unity. The tl;dr is that you shouldn’t use the ? or ?? operators with UnityEngine.Object-derived things, as they don’t work as you’d expect.

This is happening because the way Unity implemented checking for destroyed or missing components.

Unity has implemented an overload for == for UnityEngine.Object, which is the base class of all Unity-related objects. There’s two instances where Unity returns true for “x == null” when x isn’t really null:

  • If x has been destroyed, it returns true for x == null.
  • (editor only) when you call GetComponent, and there’s no such component, Unity generates an exception-generating object, which means that you get a MissingComponentException instead of a NullReferenceException. The same thing goes for accessing serialized fields that doesn’t have a component assigned. These object return true for x == null.

This causes major problems in two instances:

  • The ? and ?? operators doesn’t use the overloaded == operator for the objects, so you don’t get the custom behaviour there.
  • == is a static function, so it’s resolved at compile-time which overload to call. This means that if you reference UnityEngine.Object objects through a reference that’s either typed as an interface, or as System.Object, the overloaded == operator won’t be used.

There’s an old blog post going into some details here.

13 Likes

Ah so that’s why I never saw that in any code, because it shouldn’t be used :slight_smile:
Too bad, I hoped I could abbreviate some code.
Btw IcePhoenix: your code doesnt compile