When it comes to computing, not all devices are created equal. An action intense game that runs at 500 frames per second on a computer may only run at 12 frames per second on a mobile device. To maximize your frame rate across all platforms it is very important to use your game resources efficiently.
One of the best things you can do for your game is to use object pooling. This conserves resources by recycling a pre-defined set of objects rather than dynamically creating and destroying them as necessary.
Instantiating and destroying objects dynamically uses more memory than instantiating many objects at the start and recycling them. It makes garbage collection more predictable, eliminating a lot of hitches in the frame rate.
User Invulce from the Unity3D forums make a great object pooling script. A similar version of the script can be found below:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class ObjectPool : MonoBehaviour {
public static ObjectPool instance;
public GameObject[] objectPrefabs;
public List<GameObject>[] pooledObjects;
public int[] amountToBuffer;
protected GameObject containerObject;
void Awake() {
instance = this;
}
void Start() {
containerObject = new GameObject("ObjectPool");
pooledObjects = new List<GameObject>[objectPrefabs.Length];
int i = 0;
for(int j = 0; j < objectPrefabs.Length; j++) {
pooledObjects[i] = new List<GameObject>();
int bufferAmount = amountToBuffer[i];
for(int n = 0; n < bufferAmount; n++) {
GameObject newObj = Instantiate(objectPrefabs[j]) as GameObject;
newObj.name = objectPrefabs[j].name;
PoolObject(newObj);
}
i++;
}
}
public GameObject GetObjectForType(string objectType, bool onlyPooled) {
for(int i = 0; i < objectPrefabs.Length; i++) {
GameObject prefab = objectPrefabs[i];
if(prefab.name == objectType) {
if(pooledObjects[i].Count > 0) {
GameObject pooledObject = pooledObjects[i][0];
pooledObjects[i].RemoveAt(0);
pooledObject.transform.parent = null;
pooledObject.SetActive(true);
return pooledObject;
} else if(!onlyPooled) {
return Instantiate(objectPrefabs[i]) as GameObject;
}
break;
}
}
return null;
}
public void PoolObject(GameObject obj) {
for(int i = 0; i < objectPrefabs.Length; i++) {
if(objectPrefabs[i].name == obj.name) {
obj.SetActive(false);
obj.transform.parent = containerObject.transform;
pooledObjects[i].Add(obj);
return;
}
}
}
}
To use the script, attach it to an empty game object on your scene. In your project inspector, add all your desired prefabs to the objectPrefabs array and using the same order, determine how many prefabs you’d like to instantiate using the amountToBuffer array.
In the above screenshot you’ll notice the objectPrefabs array has two prefabs. Element 0 is circle and Element 1 is square. In the amountToBuffer array you’ll notice Element 0 is 10 and Element 1 is 5. This means that our object pool will have 10 circles and 5 squares generated.
To use an available object from the pool you can use this command from any one of your scripts on the scene:
ObjectPool.instance.GetObjectForType(string ObjectType, bool OnlyPooled);
objectType
is the name of the prefab you’d like to grab from the pool and if you set onlyPooled
to true, it will instantiate the prefab if there isn’t one available. Personally I’d rather generate enough at the start than instantiate them dynamically.
To add the object back into the pool when finished, make use of the following command:
ObjectPool.instance.PoolObject(GameObject gameObject);