Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Simple question about null conditional operator

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

  1. deLord

    deLord

    Joined:
    Oct 11, 2014
    Posts:
    281
    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,407
    I imagine it's because radius isn't a nullable type.
     
  3. deLord

    deLord

    Joined:
    Oct 11, 2014
    Posts:
    281
    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:
    28
    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:
    5,090
    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.
     
  6. deLord

    deLord

    Joined:
    Oct 11, 2014
    Posts:
    281
    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
     
unityunity