从列表中选择gameObject的实例

时间:2015-12-12 17:02:13

标签: c# unity3d pooling

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

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

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

当我通过&#34; Square&#34; gameObject到方法,它仍然选择一个&#34; Circle&#34;项目

1 个答案:

答案 0 :(得分:1)

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

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&gt;来优化它们。当你寻找正方形时,这将节省圆圈的迭代。此外,您可以检查预制件是否已在字典中注册,这样您就不会进行任何迭代。 IPoolItem还可以包含一个充当OnEnable的Init方法,这样当你弹出一个项目时你也可以初始化它。

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