1
\$\begingroup\$

I have a script that destroys the player object when a collider with that script touches it. The thing is that, even if there is no time specified in the script, it takes couple seconds before it destroys the player. Why does this happen, and how do I get around it?

public class DestroyScript : MonoBehaviour 
{
    public GameObject player;

    void OnTriggerEnter(Collision otherObj)
    {
        if (otherObj.gameObject.tag == "Player")
            Destroy(player);
    }
}
\$\endgroup\$
5
  • \$\begingroup\$ It's because Destroy called on a GameObject will Invoke Destroy on each of the Components and Objects held by this GameObject try to make an Coroutine which will destroy Components one by one instead of all at once. \$\endgroup\$
    – mrogal.ski
    Feb 8, 2017 at 19:45
  • \$\begingroup\$ Thanks. Anyway , I changed my code to : public class DestroyScript : MonoBehaviour { public GameObject player; // Use this for initialization void Start () { } // Update is called once per frame void OnTriggerEnter(Collider otherObj) { if(otherObj.gameObject.tag == "Player") Destroy(otherObj.gameObject); } \$\endgroup\$ Feb 8, 2017 at 19:52
  • \$\begingroup\$ You cannot "destroy" an object in a managed environment. The most Unity can do is set the object to null, along with every child entity it owns. This leads me to believe that your design is fatally flawed, much as your understanding is of how Unity works. I'm downvoting for blatant lack of personal research, \$\endgroup\$
    – Krythic
    Feb 9, 2017 at 0:41
  • \$\begingroup\$ @Krythic, the question specifically only asks about calling 'Destroy()' on the object. I think it is safe to assume that this functionality is the expected functionality when the asked reports "destroying the player". You can do this quite easily, in Unity. If your still confused, I can link some basic tutorials or examples that demonstrate this. \$\endgroup\$
    – Gnemlock
    Feb 9, 2017 at 11:21
  • 1
    \$\begingroup\$ @Krythic, it appears to me that you may be the one who misunderstands Unity's workings. The GameObject that our managed C# scripts reference is actually a wrapper linking to a corresponding piece of data in unmanaged code. When Unity decides to delete that backing object, it can do so with impunity. It then sets the managed GameObject into a special state where it compares as equal to null but is not actually null (generating MissingReferenceExceptions when you try to use it), until all references to it are cleared/go out of scope as per usual \$\endgroup\$
    – DMGregory
    Mar 26, 2017 at 16:04

1 Answer 1

1
\$\begingroup\$

Destroy() does not have an immediate affect on a GameObject. As m.rogalski points out, Destroy() ensures that the GameObject is destroyed safely. There are a couple of ways around this. If we want the GameObject to be immediately invisible to the game, we can use SetActive(). If we really need to, we can use DestroyImmediate(), though usage is unadvised.

Making the GameObject invisible as we Destroy() it

If you want the GameObject to be immediately invisible to the player, when you call Destroy(), you should also call SetActive(false). This will deactivate the GameObject, and remove it from play, while letting it idle in the background until it's Destroy() method completes.

public class DestroyScript : MonoBehaviour 
{
    public GameObject player;

    void OnTriggerEnter(Collision otherObj)
    {
        if (otherObj.gameObject.tag == "Player")
        {
            player.SetActive(false);
            Destroy(player);
        }
    }
}

Using DestroyImmediate()

If you just want to immediately Destroy() a GameObject, call DestroyImmediate(), instead. Be advised: DestroyImmediate() is extremely unsafe. It is advised that this method is used sparingly, and only for editor tasks; I typically use an #if UNITY_EDITOR to ensure that an actual build still uses Destroy(), instead.

public class DestroyScript : MonoBehaviour 
{
    public GameObject player;

    void OnTriggerEnter(Collision otherObj)
    {
        if (otherObj.gameObject.tag == "Player")
        {
            #if UNITY_EDITOR
            DestroyImmediate(player);
            #else
            Destroy(player);
            #endif
        }
    }
}

It is very important to note the overload for DestroyImmediate(); while you provide an Object, much like Destroy(), you can also provide a bool to permit asset deletion. This bool defaults to false, but it is important to know that the functionality there can permanently delete assets.

public class DestroyScript : MonoBehaviour 
{
    public GameObject player;

    void OnTriggerEnter(Collision otherObj)
    {
        if (otherObj.gameObject.tag == "Player")
        {
            // I am now permitting permanent asset deletion. 
            // This can be real bad, mmkay?
            #if UNITY_EDITOR
            DestroyImmediate(player, true);
            #else
            Destroy(player);
            #endif
        }
    }
}
\$\endgroup\$
5
  • 1
    \$\begingroup\$ Is there any source on why the DestroyImmediate is unsafe? I mean I'll take your word for it and just try not to use it but it'd be nice to know why it's unsafe too. \$\endgroup\$ Feb 9, 2017 at 10:58
  • 1
    \$\begingroup\$ @John Hamilton, only speculation, but I believe it circumnavigates cleanup (it was mentioned that Destroy() is slower as it makes sure each component is destroyed, too). There is also the fact that you can permanently delete assets. If you send in a reference to a game object in your assets (I.e. a prefab), and set the Boolean flag to true, it will delete the prefab. It also states that it is unsafe in the official documentation I linked. \$\endgroup\$
    – Gnemlock
    Feb 9, 2017 at 11:16
  • \$\begingroup\$ This issue looks a bit funny to me. Even though Destroy does defer actual destruction, the docs say it waits only until the end of a given frame's updates, before rendering for that frame. I've never observed a lag like the one described in the question, so I wonder whether there might be something else going on here - say one of a dozen common errors in setting up physics so the collision isn't detected & OnTriggerEnter called until later than expected. \$\endgroup\$
    – DMGregory
    Mar 26, 2017 at 16:17
  • \$\begingroup\$ @DMGregory, all I could put it down to was user configuration error, but it does seem odd. \$\endgroup\$
    – Gnemlock
    Mar 26, 2017 at 18:15
  • \$\begingroup\$ this solution works for me! thanks so much!!! \$\endgroup\$
    – Tina Lee
    Aug 20, 2020 at 11:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .