I would like to test and see if a gameobject is an instance of another gameobject, but what I have doesn't seem to be working. I am trying to make a pooling script to pool items instead of creating/destroying them.
Here is what I am currently doing:
// 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();
}
What is happening is that it just selects the first item in the list.
Take this hierarchy for example:
Circle (Clone)
Circle (Clone)
Circle (Clone)
Square (Clone)
Square (Clone)
Square (Clone)
Square (Clone)
When I pass a "Square" gameObject to the method, it still selects a "Circle" item.
What you should be doing is to assign the prefab to each instance.
public interface IPoolItem{ GameObject Prefab { get;set; } }
Make your collection of that type as well instead of GameObject. When you create a new item and place it in the pool, you also assign the prefab to it:
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);
}
}
}
The assignment should be in Create (but I don't have it in your question) and it should also check first that the object contains a IPoolItem component. Then it pushes the reference in the list.
Then you can iterate through your collection of pooled item and get one that is inactive. Then you compare its prefab to the prefab passed to the method:
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;
}
There are ways to optimise it all with a Dictionary> which would spare the iteration of circles when you look for squares. Also, you could check if the prefab is registered in the dictionary so that you don't iterate for nothing. The IPoolItem could also contain a Init method that would act as a OnEnable so that when you pop an item you also initialize it.
Finally, if you'd use a Queue instead of a List you could Dequeue when getting and Enqueue when resetting. Then you don't need to iterate since your queue contains a valid item on the front or is empty.