销毁数组中的游戏对象
本文关键字:游戏 对象 数组 | 更新日期: 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);
}
}
}