从列表中选择游戏对象的实例

本文关键字:对象 实例 游戏 选择 列表 | 更新日期: 2023-09-27 18:26:29

我想测试一下游戏对象是否是另一个游戏对象的实例,但我所拥有的似乎不起作用。我正在尝试制作一个池化脚本来池化项目,而不是创建/销毁它们。

以下是我目前正在做的事情:

// Holds all the items that can be instantiated
private List<PoolItems> poolItems = new List<PoolItems>();
// Holds all the pooled items (displayed in the hierarchy active/inactive)
private List<GameObject> gameObjects = new List<GameObject>();
// Here is how I initiate pool items:
void Start(){
    for(int i = 0; i < poolItems.Count; i++){
        GameObject obj = poolItems[i].prefab;
        for (int j = 0; j < poolItems[i].startItems; j++){
            GameObject newObj = Create(obj);
            newObj.SetActive(false);
            gameObjects.Add(newObj);
        }
    }
}
// The issue is in this method I believe:
public GameObject Instantiate(GameObject obj, Vector3 position, Quaternion rotation){
    // Find an inactive object
    GameObject foundObject = (
        from i in gameObjects
        where
            i.GetType().IsAssignableFrom(obj.GetType()) &&
            i.activeInHierarchy == false
        select i
    ).FirstOrDefault();
}

现在的情况是,它只选择了列表中的第一个项目。

以这个层次结构为例:

Circle (Clone)
Circle (Clone)
Circle (Clone)
Square (Clone)
Square (Clone)
Square (Clone)
Square (Clone)

当我将一个"方形"gameObject传递给该方法时,它仍然会选择一个"圆形"项目。

从列表中选择游戏对象的实例

您应该做的是将预制件分配给每个实例。

public interface IPoolItem{ GameObject Prefab { get;set; } }

制作该类型的收藏,而不是GameObject。当你创建一个新项目并将其放入池中时,你也会为其分配预制件:

void Start(){
    for(int i = 0; i < poolItems.Count; i++){
        GameObject obj = poolItems[i].prefab;
        for (int j = 0; j < poolItems[i].startItems; j++){
            GameObject newObj = Create(obj); 
            newObj.GetComponent<IPoolItem>().Prefab = obj;
            newObj.SetActive(false);
            gameObjects.Add(newObj);
        }
    }
}

赋值应该在Create中(但我在你的问题中没有),它还应该首先检查对象是否包含IPoolItem组件。然后它推送列表中的引用。

然后,您可以遍历池项目的集合,并获得一个不活动的集合。然后将其预制件与传递给方法的预制件进行比较:

 public GameObject Instantiate(GameObject obj, Vector3 position, Quaternion rotation){
    foreach(IPoolItem item in poolItems){
        if(item.activeSelf == true){continue;}
        if(item.Prefab == obj) { return item.gameObject;}
    }
    return null;
}

有一些方法可以通过Dictionary>来优化这一切,当你寻找正方形时,它可以省去圆形的迭代。此外,您还可以检查predb是否在字典中注册,这样就不会白白迭代。IPoolItem还可以包含一个Init方法,该方法将充当OnEnable,这样当您弹出一个项目时,您也可以对其进行初始化。

最后,如果您使用队列而不是列表,则可以在获取时退出队列,在重置时加入队列。然后您就不需要迭代了,因为您的队列前面包含一个有效的项或者是空的。