Search Unity

Checking if an object is destroyed throws MissingReferenceException

Discussion in 'Scripting' started by mr malee, Nov 15, 2012.

  1. mr malee

    mr malee

    Joined:
    Sep 19, 2012
    Posts:
    25
    How can I check if an object doesn't exist if the check for it's existence generates an error?

    Take this simple example:

    Code (csharp):
    1.  
    2. public class Test : MonoBehaviour {
    3.  
    4.     private void Start() {
    5.  
    6.         DestroyImmediate(gameObject);
    7.  
    8.         if (gameObject != null) { //generates MissingReferenceExpection
    9.  
    10.             //do something with the object if it still exists
    11.         }
    12.     }
    13. }
    14.  
    I know that example doesn't make much sense. But imagine another script trying to access the gameObject, or say an external Coroutine trying to access the object.

    Is the property "gameObject" much more complicated than I imagine? Is it attempting to find the object to which this script is attached rather than simply returning a reference to a private variable?

    The actual problem in my game is related to using Prime31's JobManager and a Bullet script.
    During the creation of a bullet, that bullet creates a Job (external coroutine) which will destroy the bullet after 2 seconds. However, the bullet has an Update method which can also destroy the bullet on contact with a solid object. If that happens and the external coroutine fires, the check to see if the bullet's gameObject exists is throwing an error.

    There are some ways to solve this though:

    1. Create reference to the Job created, if bullet hits a wall, stop the job and destroy object.
    2. Use a coroutine directly on the bullet and ignore JobManager.
    3. Put try/catch in the job's coroutine when destroying the bullet.

    Those solutions will work fine. But I still would like to know why I can't access the "gameObject" property inside a component when the GameObject has been destroyed.
     
    Last edited: Nov 15, 2012
  2. znoey

    znoey

    Joined:
    Oct 27, 2011
    Posts:
    174
    i believe you answered your own question.
    because it has been destroyed and so has the component you were accessing in the first place. If your using the job manager, its probably a separate object with a separate coroutine running. Upon death of the "bullet" it SHOULD stop this fiber since its not connected to it otherwise.
     
  3. mr malee

    mr malee

    Joined:
    Sep 19, 2012
    Posts:
    25
    the act of writing gameObject != null throws an error. This seems strange to me. The gameObject property should return null if it no longer exists, not throw an error. The error should be thrown if a property of the gameObject is accessed. Like, gameObject.name
     
  4. znoey

    znoey

    Joined:
    Oct 27, 2011
    Posts:
    174
    Also you seem to forget that Destroy() and DestroyImmediate() perform slightly different steps.
    DestroyImmediate() is like deleting something RIGHT MEOW!!! Where as Destroy is saying "I want you to die because i'm done with you, but i can wait for you to be cleaned up yourself"

    If the component your accessing is a part of the GameObject your currently attached to, then i see a huge problem with the script where your destroying itself prior to doing much.
     
  5. nullstar

    nullstar

    Joined:
    Jul 2, 2010
    Posts:
    186
    Doing: if (gameObject != null) {} is effectively short hand for doing this: if (this.gameObject != null) {}, (this is what will actualy happen internaly). The problem is that you've already destroyed the instance of the class before you reach this line of code, thus the 'this' reference is null, hence why trying to access 'this.gameObject' throws a null reference expection.
     
  6. BrUnO-XaVIeR

    BrUnO-XaVIeR

    Joined:
    Dec 6, 2010
    Posts:
    1,687
    Checking if an object was destroyed, using a script within the exactly destroyed object, absolutely makes no sense.
     
  7. mr malee

    mr malee

    Joined:
    Sep 19, 2012
    Posts:
    25
    Thanks for the replies, especially Nullstar, it's making a more sense now.

    I guess I don't really follow Unity's method of garbage collection / disposal. I'm just going to slowly back away and pretend I fully understand what's going on here. I'm coming from a flash / action script side of things. So this whole component business is very new to me.

    I just wasn't expecting "this" to ever be null, how could a script be executing if it no longer exists in memory? In my mind, after calling Destroy, if the object is truly garbage collected at that time then any remaining script shouldn't be executed from that point on. Seems weird to me that a script can still be executing even though it has been Destroyed.

    But anyway, thanks for the help.

    if (this this.gameObject) :D
     
    Last edited: Nov 17, 2012