Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

4.3 C# bugs

Discussion in 'Scripting' started by Zergling103, Nov 13, 2013.

  1. Zergling103

    Zergling103

    Joined:
    Aug 16, 2011
    Posts:
    392
    Hi there,

    It seems like the C#/Mono Unity is using is doing something a bit spooky.

    Before 4.3, the following two statements were functionally identical:

    Code (csharp):
    1.  
    2. var x = someUnityObject ?? someOtherUnityObject;
    3.  
    Code (csharp):
    1.  
    2. var x;
    3. if(someUnityObject != null)
    4. {
    5.     x = someUnityObject;
    6. }
    7. else
    8. {
    9.     x = someOtherUnityObject;
    10. }
    11.  
    But of course, the latter is much uglier than the former.

    Now with the new update, it seems that they do not behave the same. The former throws a MissingReferenceException while the latter does not. The reason behind this takes a bit to explain:

    When you have a reference to a unity object, the object in C# land (managed memory) may exist, but it may point to a game object, component, etc. that has been destroyed in C++ land (native memory). As a result, simply comparing the object to null isn't sufficient, it must be considered null if either the C# wrapper is null or the object in native code is null.
    This is why the UnityEngine.Object == operator is overloaded.

    When you use a ?? operator, you are implicitly comparing something to null. It seems that in the new update, ?? doesn't use the overloaded operator; it only checks if the wrapper is null, and doesn't check if what it's wrapping still exists.

    Previously, the ?? operator worked exactly as expected.

    This means that post v4.3 if you use the ?? operator in your code, to for example get a component or then add it if it doesn't exist, you might find your code trying to access an object or component that was destroyed, returning a MissingReferenceException; the ?? had a false positive.

    The following code has the potential to throw a missing reference exception:

    Code (csharp):
    1.  
    2. var myBehaviour = GetComponent<MyBehaviour>() ?? gameObject.AddComponent<MyBehaviour>();
    3.  
    4. // May throw MissingReferenceException because GetComponent() may actually return an object even if the object it represents has been Destroy()'ed.
    5. myBehaviour.name = "Hello World!"
    6.  
    This is kind of scary. It's easy for us to switch out ??, or for Unity to put up a hotfix for this - but the main concern I have is what else broke? What else will break?
     
    Last edited: Nov 14, 2013
  2. Zergling103

    Zergling103

    Joined:
    Aug 16, 2011
    Posts:
    392
  3. exiguous

    exiguous

    Joined:
    Nov 21, 2010
    Posts:
    1,749
  4. Zergling103

    Zergling103

    Joined:
    Aug 16, 2011
    Posts:
    392
    Thanks for the helpful link! Interesting stuff.
     
  5. joessu

    joessu

    Joined:
    Nov 16, 2010
    Posts:
    88
    Actually that thread just proves that this is even more of a bug. This happens with just unity objects.

    It would be useful to post results of the print statements from the other thread.