Hello all! I know I know, more than 1 post in the span of a month? How lucky are you! Well the answer is you’re not, because my last post was a month and a week ago now… so calm down, you. But I do bring some cool stuff to share! Ever heard of Object Pooling in Unity? In brief: If you have a GameObject which you’re constantly creating new copies of and then destroying right after, such as a projectile or an effect, it can be really unnecessarily taxing on your CPU. So an Object Pool just instantiates all necessary instances of the GameObject at the start of the game, and just recycles them, setting them active and inactive when needed, and expanding if necessary, much like an ArrayList, to accommodate however many instances of the object your game needs.
I’m just beginning work as an engineer on a game with some of my friends at school. For now we have dubbed the game “Project Rat”, and this game is why I’ve built this Object Pooler! It’s a really easy object to build but I’ll talk a little about it. I’d like to also start by saying that I read and learned about Object Pooling from Mark Placzek. To start, we define an ObjectPoolItem Class which contains an Int that defines the initial size, a GameObject which will hold the prefab that is to be pooled, and then a bool to represent if we want this size to be dyamic, or a fixed value.
From here we define the ObjectPooler Class, which is a monoBehaviour. Here we declare the List that will be our pool, as well as the List that will contain all of the pools, for easy access by the GameManager. The pool list is then instantiated in Start(), where we then have a loop instantiating as many copies of the GameObject as defined in our ObjectPoolItem (both the GameObject and the size are defined there). In this loop the newly instantiated GameObject is set inactive then added to our List.
And… That’s really it! Then just create a function that takes a string of the tag of item being sought, and returns the first instance of an item with that tag which isn’t already .activeInHeirarchy(). It’s here that we can also create a check on the size of the List and compare it to how far we have to go into our List to get a new GameObject, and decide if we want the List to expand or not, using the bool we defined in the ObjectPoolItem, and just instantiating a new GameObject as we did in Start().
Sweet! Now you just need to keep in mind that the Object Pooler is storing inactive GameObjects, so however you call them you must remember to set them active! And then set inactive once they are no longer in use so that they may be recycled by our object pool! Here’s some code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//Declares necessary values
[System.Serializable]
public class ObjectPoolItem
{
public int amountToPool;
public GameObject objectToPool;
public bool expand = true;
}
public class ObjectPooler : MonoBehaviour
{
public static ObjectPooler SharedInstance;
//Declares List to hold pools
public List<ObjectPoolItem> listOfPools;
//Declares List to hold GameObjects
private List<GameObject> objectPool;
void Awake()
{
SharedInstance = this;
}
void Start()
{
//Instantiates List
objectPool = new List<GameObject>();
foreach (ObjectPoolItem item in listOfPools)
{
// Instantiates the "Object to pool". sets inactive, and stores in List for number in amountToPool
for (int rep = 0; rep < item.amountToPool; rep++)
{
GameObject obj = (GameObject)Instantiate(item.objectToPool);
obj.SetActive(false);
objectPool.Add(obj);
}
}
}
//Returns an INACTIVE instance of the pooled object, need to match tag
//Can also specify when to expand and when not to.
public GameObject GetPooledObject(string tag)
{
//Cycles through active and inactive elements in List
for (int rep = 0; rep < objectPool.Count; rep++)
{
//If Inactive
if (!objectPool[rep].activeInHierarchy && objectPool[rep].tag == tag)
{
return objectPool[rep];
}
}
//expands necesary lists all at once
foreach (ObjectPoolItem item in listOfPools)
{
if (item.objectToPool.tag == tag)
{
if (item.expand)
{
GameObject obj = (GameObject)Instantiate(item.objectToPool);
obj.SetActive(false);
objectPool.Add(obj);
return obj;
}
}
}
return null;
}
}
