Search Unity

Simple question about null conditional operator

Discussion in 'Scripting' started by deLord, Aug 27, 2019.

  1. deLord

    deLord

    Joined:
    Oct 11, 2014
    Posts:
    306
    Hello
    About the the null conditional operator:

    I have 2 lines of code, the second one producing an exception
    Code (CSharp):
    1. print("1" + GameObject.Find("notExistent")?.gameObject);
    2. 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??
     
  2. Munchy2007

    Munchy2007

    Joined:
    Jun 16, 2013
    Posts:
    1,735
    I imagine it's because radius isn't a nullable type.
     
  3. deLord

    deLord

    Joined:
    Oct 11, 2014
    Posts:
    306
    no, I can also write .gameObject
    btw the exception is
    MissingComponentException: There is no 'CircleCollider2D' attached to the "GameManager" game object, but a script is trying to access it.
    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.
     
  4. IcePhoenix_0101

    IcePhoenix_0101

    Joined:
    Sep 9, 2017
    Posts:
    32
    That's because GetComponent<CircleCollider2D>() 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:

    Code (CSharp):
    1. print("2" + GameObject.Find("GameManager")?.GetComponent(typeof(CircleCollider2D))?.GetComponent<CircleCollider2D>().radius);
     
  5. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    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.
     
    HammerSun, Novack, xodennisxo and 9 others like this.
  6. deLord

    deLord

    Joined:
    Oct 11, 2014
    Posts:
    306
    Ah so that's why I never saw that in any code, because it shouldn't be used :)
    Too bad, I hoped I could abbreviate some code.
    Btw IcePhoenix: your code doesnt compile