Destroy(gameObject) not working

I have two scripts that randomly spawn models in an area and then respawn ones the overlap. I can’t find any errors in the code, but when Destroy(gameObject); is called in the second script, it seems to do nothing. Here is the base spawning script:

using UnityEngine;
using System.Collections;

public class CreateBuildings : MonoBehaviour {

    public GameObject ThreeSBWR;
    public GameObject ThreeSB;
    public GameObject TwoSBWR;
    public GameObject TwoSB;
    public GameObject OneSBWR;
    public GameObject OneSB;
    public int ThreeSBTS;
    public int TwoSBTS;
    public int OneSBTS;
    Quaternion SpawnRotation;

	void Start ()
    {
        int a;
        int b;
        int c;
        a = ThreeSBTS;
	    while (a > 0)
        {
            Vector3 SpawnLocation;
            SpawnLocation = new Vector3(Random.Range(-90, 90), 2.5f, Random.Range(-90, 90));
            while (SpawnLocation.x < 15 && SpawnLocation.x > -15 && SpawnLocation.z < 15 && SpawnLocation.z > -15)
            {
                SpawnLocation = new Vector3(Random.Range(-90, 90), 2.5f, Random.Range(-90, 90));
            }
            SpawnRotation.eulerAngles = new Vector3(0, Random.Range(0, 360), 0);
            float rand;
            rand = Random.Range(0, 1);
            if (rand >= 0.5f)
            {
                Instantiate(ThreeSB, SpawnLocation, SpawnRotation);
            }
            else
            {
                Instantiate(ThreeSBWR, SpawnLocation, SpawnRotation);
            }
            a -= 1;
        }
        b = TwoSBTS;
        while (b > 0)
        {
            Vector3 SpawnLocation;
            SpawnLocation = new Vector3(Random.Range(-90, 90), 2.5f, Random.Range(-90, 90));
            while (SpawnLocation.x < 15 && SpawnLocation.x > -15 && SpawnLocation.z < 15 && SpawnLocation.z > -15)
            {
                SpawnLocation = new Vector3(Random.Range(-90, 90), 2.5f, Random.Range(-90, 90));
            }
            SpawnRotation.eulerAngles = new Vector3(0, Random.Range(0, 360), 0);
            float rand;
            rand = Random.Range(0, 1);
            if (rand >= 0.5f)
            {
                Instantiate(TwoSB, SpawnLocation, SpawnRotation);
            }
            else
            {
                Instantiate(TwoSBWR, SpawnLocation, SpawnRotation);
            }
            b -= 1;
        }
        c = OneSBTS;
        while (c > 0)
        {
            Vector3 SpawnLocation;
            SpawnLocation = new Vector3(Random.Range(-90, 90), 2.5f, Random.Range(-90, 90));
            while (SpawnLocation.x < 15 && SpawnLocation.x > -15 && SpawnLocation.z < 15 && SpawnLocation.z > -15)
            {
                SpawnLocation = new Vector3(Random.Range(-90, 90), 2.5f, Random.Range(-90, 90));
            }
            SpawnRotation.eulerAngles = new Vector3(0, Random.Range(0, 360), 0);
            float rand;
            rand = Random.Range(0, 1);
            if (rand >= 0.5f)
            {
                Instantiate(OneSB, SpawnLocation, SpawnRotation);
            }
            else
            {
                Instantiate(OneSBWR, SpawnLocation, SpawnRotation);
            }
            c -= 1;
        }
    }
    public void Spawn(GameObject ToSpawn)
    {
        print("Call Successfull");
        Vector3 SpawnLocation;
        SpawnLocation = new Vector3(Random.Range(-90, 90), 2.5f, Random.Range(-90, 90));
        while (SpawnLocation.x < 15 && SpawnLocation.x > -15 && SpawnLocation.z < 15 && SpawnLocation.z > -15)
        {
            SpawnLocation = new Vector3(Random.Range(-90, 90), 2.5f, Random.Range(-90, 90));
        }
        Quaternion SpawnRot;
        SpawnRot = new Quaternion(0, 0, 0, 0);
        SpawnRot.eulerAngles = new Vector3(0, Random.Range(0, 360), 0);
        Instantiate(ToSpawn, SpawnLocation, SpawnRot);
        print("(Call) Spawn Complete");
    }
}

Here is the script that checks for overlaps:

using UnityEngine;
using System.Collections;

public class CollisionCheck : MonoBehaviour {

    void OnTriggerEnter(Collider col)
    {
        if (col.gameObject.name != "Player" && col.gameObject.name != "Ground" && col.gameObject.name != "Bullet(Clone)")
        {
            GameObject.Find("GameController").GetComponent<CreateBuildings>().Spawn(gameObject);
            print("Called");
            Destroy(gameObject);
        }
    }
    void OnTriggerStay(Collider col)
    {
        if (col.gameObject.name != "Player" && col.gameObject.name != "Ground" && col.gameObject.name != "Bullet(Clone)")
        {
            GameObject.Find("GameController").GetComponent<CreateBuildings>().Spawn(gameObject);
            print("Called");
            Destroy(gameObject);
        }
    }
}

Here is a video showing what happens with different values for ThreeSBTS, TwoSBTS, and OneSBTS:

https://drive.google.com/open?id=0B_HzgsC9lP3nRURlaDUxQlJIOEk

As you can see in the video, the Destroy(gameObject); seems to do nothing, and the more buildings there are to spawn, the more likely that this causes problems. I would like to have 2, 4, and 6 as the values, but it rarely spawns correctly. Does anyone know how to fix this?

Hello @matthrewp,

You’re calling Instantiate on an object marked for Destroy. I would make a function to Move the colliding building instead of re-spawning it.

My solution (keeping your original approach) would be as follows:

Create a function to only move the buildings to a new random location. On collision enter, call this function. Just in case, I would add a maximum amount of times you can call this and check for it every call before ultimately destroying the conflicting gameObject (to avoid callstack overflows).


Some other general tips for you:

I would start by removing the OnTriggerStay function so that it doesn’t interfere with your debugging. Having two Debug.Log’s that print “Called” makes it harder to know which function was called (and we only need to destroy once: when the overlap begins).

Second, I see you want to re-spawn the buildings that overlap others but you’re actually calling Destroy on both buildings (both buildings collide with each other).

And lastly, the video shows only the first frame since you pause it and then press play. Wouldn’t you want to see what happens the next frame? (Destroy waits until the end of the current loop to safely destroy the gameobject, more info here).

I have had a similar problem as well.

Some solutions I thought of:
Destroy(this) instead of Destroy(gameObject)

The only solution that always worked for me was having a separate script delete things.
Camera.main.gameObject.GetComponent<CustDelete>().Destroy(this);

CustDelete.cs:

`
using UnityEngine;
using System.Collections

public class CustDelete : MonoBehaviour {

public void Destroy(GameObject des) {

Destroy(des);

}

}
`

It is a Unity Bug I believe because it deletes the object before the script knows it ended (idk what actually happens)