You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

155 lines
4.8 KiB

/*
* Unless otherwise licensed, this file cannot be copied or redistributed in any format without the explicit consent of the author.
* (c) Preet Kamal Singh Minhas, http://marchingbytes.com
* contact@marchingbytes.com
*/
// modified version by Kanglai Qian
using UnityEngine;
using System.Collections.Generic;
namespace ET
{
public enum PoolInflationType
{
/// When a dynamic pool inflates, add one to the pool.
INCREMENT,
/// When a dynamic pool inflates, double the size of the pool
DOUBLE
}
public class GameObjectPool
{
private Stack<PoolObject> availableObjStack = new Stack<PoolObject>();
//the root obj for unused obj
private GameObject rootObj;
private PoolInflationType inflationType;
private string poolName;
private int objectsInUse = 0;
public GameObjectPool(string poolName, GameObject poolObjectPrefab, GameObject rootPoolObj, int initialCount, PoolInflationType type)
{
if (poolObjectPrefab == null)
{
#if UNITY_EDITOR
Debug.LogError("[ObjPoolManager] null pool object prefab !");
#endif
return;
}
this.poolName = poolName;
this.inflationType = type;
this.rootObj = new GameObject(poolName + "Pool");
this.rootObj.transform.SetParent(rootPoolObj.transform, false);
// In case the origin one is Destroyed, we should keep at least one
GameObject go = GameObject.Instantiate(poolObjectPrefab);
PoolObject po = go.GetComponent<PoolObject>();
if (po == null)
{
po = go.AddComponent<PoolObject>();
}
po.poolName = poolName;
AddObjectToPool(po);
//populate the pool
populatePool(Mathf.Max(initialCount, 1));
}
//o(1)
private void AddObjectToPool(PoolObject po)
{
//add to pool
po.gameObject.SetActive(false);
po.gameObject.name = poolName;
availableObjStack.Push(po);
po.isPooled = true;
//add to a root obj
po.gameObject.transform.SetParent(rootObj.transform, false);
}
private void populatePool(int initialCount)
{
for (int index = 0; index < initialCount; index++)
{
PoolObject po = GameObject.Instantiate(availableObjStack.Peek());
AddObjectToPool(po);
}
}
//o(1)
public GameObject NextAvailableObject(bool autoActive)
{
PoolObject po = null;
if (availableObjStack.Count > 1)
{
po = availableObjStack.Pop();
}
else
{
int increaseSize = 0;
//increment size var, this is for info purpose only
if (inflationType == PoolInflationType.INCREMENT)
{
increaseSize = 1;
}
else if (inflationType == PoolInflationType.DOUBLE)
{
increaseSize = availableObjStack.Count + Mathf.Max(objectsInUse, 0);
}
#if UNITY_EDITOR
Debug.Log(string.Format("Growing pool {0}: {1} populated", poolName, increaseSize));
#endif
if (increaseSize > 0)
{
populatePool(increaseSize);
po = availableObjStack.Pop();
}
}
GameObject result = null;
if (po != null)
{
objectsInUse++;
po.isPooled = false;
result = po.gameObject;
if (autoActive)
{
result.SetActive(true);
}
}
return result;
}
//o(1)
public void ReturnObjectToPool(PoolObject po)
{
if (poolName.Equals(po.poolName))
{
objectsInUse--;
/* we could have used availableObjStack.Contains(po) to check if this object is in pool.
* While that would have been more robust, it would have made this method O(n)
*/
if (po.isPooled)
{
#if UNITY_EDITOR
Debug.LogWarning(po.gameObject.name + " is already in pool. Why are you trying to return it again? Check usage.");
#endif
}
else
{
AddObjectToPool(po);
}
}
else
{
Debug.LogError(string.Format("Trying to add object to incorrect pool {0} {1}", po.poolName, poolName));
}
}
}
}