销毁数组中的游戏对象

本文关键字:游戏 对象 数组 | 更新日期: 2023-09-27 18:14:14

当玩家进入触发器时,我有一个数组来实例化多个游戏对象,但我不知道如何在玩家退出触发器时销毁这些游戏对象。这是我的代码:

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);
    }
}
}
更新代码:

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));
    }
}
}

销毁数组中的游戏对象

目前你不存储对实例化的游戏对象的引用。

为此,您可以创建另一个列表并添加实例化的对象,就像这样(这是一个简短的版本,您也可以将它们存储在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));
    }
}

然后用于销毁:

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

还有其他方法。例如,如果你不想每次都重新初始化列表,你可以在销毁它们之前从列表中删除项。在这种情况下,您需要从后到前迭代列表。(同样,使用上述方法,如果对象明显被销毁,则不能尝试引用列表中的内容,因为这会引发错误。)

另一种方法是在实例化时将游戏对象作为子对象添加到某个父对象,并迭代它们以进行销毁,例如

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

遍历列表以销毁每个对象,然后创建一个删除空对象的新列表:

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

注意,当从列表中删除空对象时,您需要等待下一帧对象被实际销毁并成为列表中的空对象,因此您可以在一帧后的IEnumerator函数中清除列表,示例脚本如下:

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);
    }
}

}