如何在运行时销毁多个游戏对象?

5
在Unity3D中,我正在运行时动态创建和销毁胶囊。我使用“空格键”来创建胶囊,“C键”来销毁胶囊。
我想同时创建多个对象并销毁多个对象。当我按下“空格键”多次时,对象会被多次创建,这没问题。
但问题是,当我多次按下“C键”时,只有一个对象被销毁。我如何实现逐个销毁多个对象?
 using System;
 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;

 public class DynamicCreate : MonoBehaviour 
 {     
     public GameObject caps;

     // Update is called once per frame
     void Update () 
     {
          if (Input.GetKeyDown(KeyCode.Space))
          {
               createObject();
          }

          if (Input.GetKeyDown(KeyCode.C))
          {
               destroyObject();
          }
     }

     private void createObject()
     {
          caps = GameObject.CreatePrimitive(PrimitiveType.Capsule);
     }

     public void destroyObject()
     {
          Destroy(caps);
     }
}
2个回答

4
您可以简单地创建一个胶囊列表。 像下面这样声明一个胶囊列表:
List<GameObject> Capsules;
void Start()
{
    Capsules=new List<GameObject>();
}

将任何已创建的胶囊添加到列表中:
private void createObject()
{
    caps = GameObject.CreatePrimitive(PrimitiveType.Capsule);
    Capsules.Add(caps);
}

您可以在列表中销毁这些胶囊:

public void destroyObject()
{
    foreach(GameObject capsule in Capsules)
    {
        Destroy(capsule);
    }
}

看看是否有帮助。

它会一次性删除所有游戏对象。我想要逐个删除,每按下一个 C 键删除一个。 - Every Thing
1
@EveryThing 在 destoryObject 中每次只获取一个元素。 - killer_mech
@killer_mech,你能帮我吗? - Every Thing
@bolkay,请帮我解决下面的问题:https://stackoverflow.com/questions/53984168/how-to-add-fbx-human-3d-object-in-gameobject-createprimitive-in-unity-c-s - Every Thing

3
我想为bolkay的回答增加一些内容。如果您想逐个添加和删除最佳数据结构,则最好使用队列。
Queue<GameObject> Capsules;
void Start()
{
    Capsules = new Queue<GameObject>();
}

private void createObject()
{
    GameObject caps = GameObject.CreatePrimitive(PrimitiveType.Capsule);
    Capsules.Enqueue(caps);
}

public void destroyObject()
{
    if(Capsules.Count > 0)
        Destroy(Capsules.Dequeue());   
}

队列数据结构会按照先进先出的原则提供元素。因此,它会在运行时首先提供您添加到队列中的第一个游戏对象,并且您不需要像使用List时那样管理索引变量。


注意:这个解决方案仍然非常基础,但我建议您使用对象池而不是在运行时创建和销毁对象,因为在运行时创建和销毁对象会相当耗费资源。因此,除非绝对必要,否则应避免创建和删除。
Queue<GameObject> pooledObjects;
Queue<GameObject> Capsules;
void Start()
{
    pooledObjects = new Queue<GameObject>();

    Capsules = new Queue<GameObject>();
}

private void createObject()
{
    if(pooledObjects.Count > 0)
    {
        GameObject fetchedObject = pooledObjects.Dequeue();
        fetchedObject.SetActive(true);
        //Do translations,scaling or other stuff on this reference

        //Add it back to main list of things present in scene.
        Capsules.Enqueue(fetchedObject);
    } else
    {
        //Only create objects if necessary
        GameObject caps = GameObject.CreatePrimitive(PrimitiveType.Capsule);
        Capsules.Enqueue(caps);
    }            
}

public void destroyObject()
{
    //here instead of destorying the object we will just disable them and keep them out if scene so we dont have to recreate them everytime
    if(Capsules.Count > 0)
    {
        GameObject fetchedObject = Capsules.Dequeue();
        fetchedObject.SetActive(false);//Turn the object off from scene
        pooledObjects.Equals(fetchedObject);
    }   
}

这里是C#支持的数据结构列表,根据您的需求情况,您可能需要使用其中之一。


我还有一个问题,我们可以为它提供唯一的ID吗? - Every Thing
1
对于唯一标识符,有多种处理方式。您可以将其保存在Dictionary<int,GameObject>中,也可以拥有一个Class对象列表,其中类具有以下变量作为id和gameobject,并通过与id匹配来从列表中查找其引用。 - killer_mech
在第二段代码中,如果我创建了多个对象并且只在使用后禁用,那么禁用的对象数量将增加,如果我想重复使用禁用的对象呢? - Every Thing
1
GameObject fetchedObject = pooledObjects.Dequeue(); fetchedObject.SetActive(true);这段代码会重复使用已禁用的对象,如果它们存在的话。 - killer_mech
这并不是使用队列而不是像队列一样处理列表的一个真正好的理由。使用列表可以避免包含.NET运行时的部分(队列不是核心系统的一部分,而列表是)。 - Ed Marty
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接