Select 列表中的游戏对象实例

Select an instance of a gameObject from a List

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

这是我目前正在做的事情:

// 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)

当我将一个 "Square" 游戏对象传递给该方法时,它仍然选择了一个 "Circle" 项目。

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

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

有多种方法可以使用词典> 优化这一切,这样可以在您查找正方形时避免循环迭代。此外,您可以检查预制件是否已在字典中注册,这样您就不会无缘无故地进行迭代。 IPoolItem 还可以包含一个用作 OnEnable 的 Init 方法,这样当您弹出一个项目时,您也可以对其进行初始化。

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