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 方法,这样当您弹出一个项目时,您也可以对其进行初始化。
最后,如果您使用队列而不是列表,您可以在获取时出队,在重置时入队。然后你不需要迭代,因为你的队列在前面包含一个有效的项目或者是空的。
我想测试并查看一个游戏对象是否是另一个游戏对象的实例,但我所拥有的似乎不起作用。我正在尝试制作一个池化脚本来池化项目而不是 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 方法,这样当您弹出一个项目时,您也可以对其进行初始化。
最后,如果您使用队列而不是列表,您可以在获取时出队,在重置时入队。然后你不需要迭代,因为你的队列在前面包含一个有效的项目或者是空的。