Angelsm
Angelsm

Reputation: 339

Destroy the gameobjects of an array

I have an array to instantiate multiple gameobjects when the player enters on a trigger but I don't know how to destroy these gameobjects when the player exits the trigger. This is my code:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class SpawnDestroy : MonoBehaviour {

public List<GameObject> spawnPositions;
public List<GameObject> spawnObjects;


void OnTriggerEnter(Collider other)
{

    if (other.gameObject.tag == "Player")
    {
        SpawnObjects ();
    }
}

void OnTriggerExit(Collider other)
{

    if (other.gameObject.tag == "Player")
    {

    ............

    }
}

void SpawnObjects()
{
    foreach(GameObject spawnPosition in spawnPositions)
    {
        int selection = Random.Range(0, spawnObjects.Count);
        Instantiate(spawnObjects[selection], spawnPosition.transform.position, spawnPosition.transform.rotation);
    }
}

}

UPDATE CODE:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;


public class SpawnDestroy : MonoBehaviour {

public List<GameObject> spawnPositions;
public List<GameObject> spawnObjects;
private List<GameObject> instantiated;


void OnTriggerEnter(Collider other)
{

    if (other.gameObject.tag == "Player")
    {
        SpawnObjects ();
    }
}

void OnTriggerExit(Collider other)
{

    if (other.gameObject.tag == "Player")
    {

        for(int i = 0; i < instantiated.Count; i++)
        {
            Destroy(instantiated[i]);
        }

        }
}

void SpawnObjects()
{
    // (re-)initialize as empty list
    instantiated = new List<GameObject>();

    foreach(GameObject spawnPosition in spawnPositions)
    {
        int selection = Random.Range(0, spawnObjects.Count);
        instantiated.Add(Instantiate(spawnObjects[selection], spawnPosition.transform.position, spawnPosition.transform.rotation));
    }
}

}

Upvotes: 1

Views: 5149

Answers (2)

Liam
Liam

Reputation: 400

Iterate through the list to destroy each object, then create a new list where null objects are removed:

public List<GameObject> list;    
foreach (GameObject item in list) { Destroy(item); }
list.RemoveAll(GameObject => GameObject == null); // or do list = new List<GameObject>();

Note, when removing null objects from a list you need to wait for the next frame for the object to actually be destroyed and become a null object in the list, so you could clean the list in an IEnumerator function a frame later, example script below:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;    
public class ListCLeaner: MonoBehaviour
{
    public List<GameObject> list;    
    public void ClearList(){
        foreach (GameObject item in list) { Destroy(item); }
        StartCoroutine(CleanListAfterFrame());
    }
    IEnumerator CleanListAfterFrame(){
        yield return new WaitForEndOfFrame();
        list.RemoveAll(GameObject => GameObject == null);
    }
}

}

Upvotes: 0

Gunnar B.
Gunnar B.

Reputation: 2989

Currently you don't store a reference to the instantiated gameobjects.

For this you can create another list and add the instantiated objects, something like this (this is a short version, you could also store them in a temp):

private List<GameObject> instantiated;

...

void SpawnObjects()
{
    // (re-)initialize as empty list
    instantiated = new List<GameObject>();

    foreach(GameObject spawnPosition in spawnPositions)
    {
        int selection = Random.Range(0, spawnObjects.Count);
        instantiated.Add((GameObject)Instantiate(spawnObjects[selection], spawnPosition.transform.position, spawnPosition.transform.rotation));
    }
}

And then for destroying:

for(int i = 0; i < instantiated.Count; i++)
{
    Destroy(instantiated[i]);
}

There are other ways too. E.g. if you don't want to re-initialize the list every time, you can remove the items from the list before destroying them. In this case you need to iterate the list from back to front though. (Also, with the above, you must not try to reference something from the list if the objects were destroyed obviously, since this would raise an error.)

Another way would be to add the gameobjects as child to a certain parent upon instantiation and iterate them for destroying, something like

while(parentTransform.childCount > 0)
{
    Transform child = parentTransform.GetChild(0);
    Destroy(child.gameObject);
    child.SetParent(null);
}

Upvotes: 3

Related Questions