So another fellow was doing a journal and was a little nervous about posting code for review. It got me thinking that I should post some code up as well. (I do have a game update that I could do as well, but I'll save that for later)
Anyway, my game spawns a lot of random levels that are populated with random amounts of game objects, and rather than use GameObject.Instantiate and Destroy repeatedly, I decided to pool the objects and re-use them. I looked around online for free ones, saw someone posted theirs, but... I didn't like it, but it did give me a good base to strip out and make my own:[code=js:0]//This is a heavy modification of the original code found here: http://forum.unity3d.com/threads/simple-reusable-object-pool-help-limit-your-instantiations.76851/using UnityEngine;using System.Collections.Generic;public class GameObjectPooler : MonoBehaviour{ // TODO: I could probably re-work this to get rid of the singleton public static GameObjectPooler Current; //A public static reference to itself (make's it visible to other objects without a reference) public GameObject[] prefabs; //Collection of prefabs to be pooled HashSet prefabSet = new HashSet(); // internally we use this, makes it easier to programmatically add other prefabs to the pooler if we want Dictionary> pooledObjects; // key = prefab, value = list of pooled objects Dictionary instancedPoolObjects; // Key = instance, Value = prefab public int[] amountToBuffer; //The amount to pool of each object. This is optional public int defaultBufferAmount = 10; //Default pooled amount if no amount abaove is supplied GameObject containerObject; //A parent object for pooled objects to be nested under. Keeps the hierarchy clean void Awake() { //Ensure that there is only one object pool if (Current == null) { Current = this; } else { Debug.LogError("Attempting to spawn a second GameObjectPooler!"); Destroy(gameObject); } //Create new container containerObject = new GameObject("ObjectPool"); //Create new list for objects pooledObjects = new Dictionary>(); instancedPoolObjects = new Dictionary(); int index = 0; foreach (GameObject objectPrefab in prefabs) { int bufferAmount; if (index < amountToBuffer.Length) bufferAmount = amountToBuffer[index]; else bufferAmount = defaultBufferAmount; AddPrefab(objectPrefab, bufferAmount); // Go to the next prefab in the collection index++; } } public void AddPrefab(GameObject prefab) { AddPrefab(prefab, defaultBufferAmount); } public void AddPrefab(GameObject prefab, int startPoolSize) { if(!prefabSet.Add(prefab)) { Debug.LogError("Trying to add prefab that already exists in the GameObjectPooler"); } pooledObjects.Add(prefab, new Stack()); for (int i = 0; i < startPoolSize; i++) { CleanPoolObject((GameObject)Instantiate(prefab)); } } public GameObject GetObject(GameObject objectType) { Debug.Assert(pooledObjects.ContainsKey(objectType), "objecttype: " + objectType.ToString() + " not found in pool, did you add it to the GameObjectPooler?", objectType); GameObject returnObj = null; //If there are any left in the pool... if (pooledObjects[objectType].Count > 0) { GameObject pooledObject = pooledObjects[objectType].Pop(); pooledObject.transform.parent = null; returnObj = pooledObject; } else // I am just always allow growing, TODO: Grow by more than 1 at a time. { GameObject obj = Instantiate(objectType) as GameObject; returnObj = obj; } if(!instancedPoolObjects.ContainsKey(returnObj)) { instancedPoolObjects.Add(returnObj, objectType); } returnObj.SetActive(true); return returnObj; } public void PoolObject(GameObject obj) { CleanPoolObject(obj); Debug.Assert(instancedPoolObjects.ContainsKey(obj), "Object not found in pool: " + obj.name, obj); pooledObjects[instancedPoolObjects[obj]].Push(obj); instancedPoolObjects.Remove(obj); // this causes a bit of churn, but is handy for keeping track of all instances over pooled } // Be very careful with this. If anyone is holding any references to a pooled object, things get wonky public void PoolAllObjects() { foreach(var key in instancedPoolObjects.Keys) { CleanPoolObject(key); pooledObjects[instancedPoolObjects[key]].Push(key); } instancedPoolObjects.Clear(); } private void CleanPoolObject(GameObject obj) { //obj.SendMessage("OnClean"); // OnDisable gets called intrinsically obj.SetActive(false); obj.transform.parent = containerObject.transform; }}
Then you'd have strongly typed values stored and wouldn't have to cast them to their real types. But after thinking about it, I don't know which is better for you.
I'm also not sure you want your Pooler to inherit from MonoBehaviour (or if Unity supports generic MonoBehaviour scripts). Instead the pooler could be a regular class that's contained by a different component.
Just something to think about.