Pool System Using Unity 2021+

Pauline Pun
Mighty Bear Games
Published in
5 min readSep 15, 2022

When you instantiate 1 object in Unity, it’s as easy as a breeze. But what happens when you try doing the same for 1000 objects? Notice that slight pause?

Photo by Mulyadi on Unsplash

It’s not going to be a pleasant experience if every time you enter a room, the game freezes and NPCs start popping out of nowhere to start attacking you. So here’s where pooling of GameObjects comes in.

In the following tutorial we’ll be looking at:

  • Using unity’s IObjectPool to create resources
  • Creating a pool item — this holds data to the GameObject
  • Creating a pool manager — collection of the pool item
  • The pooled GameObject — how to return itself back to the pool manager when done
  • Spawning a pooled GameObject — how to request from the pool manager and return it
  • Tying it all together

IObjectPool

With Unity 2021+, Unity has released a set of pool API which makes creation of a pooling system a lot easier. It provides different collection types which you can use depending on your needs. The APIs are relatively straightforward and all you need to do to get started is, use Unity 2021+ and include the following in your script

using UnityEngine.Pool;

Since you’re reading this, I’m assuming that you already know the importance having a pool system, so let’s jump straight into implementation.

Creating A Pool Item

This will be our container class to store the pool data.

Prefab
Prefab object which is used for instantiating the pooled object.

PoolCount
The number of pooled GameObjects to be created.

Pool Manager

This will be the bulk of our logic. Here we will store the pool item data and use it to create the pooled GameObjects.

We will be using IObjectPool for each pooled collection. It’s important to note that IObjectPool uses a stack for implementation; this will affect how we create the GameObjects later. A dictionary is used to store all these collections.

DEFAULT_POOL_COUNT
Remember the PoolItem earlier on? We can use this to set a default count value for it.

poolableObjects
Collection of the pool item data which will be used to create the pooled GameObjects.

collectionChecks
Parameter used to initialise the IObjectPool. This will throw an exception when you try to release a GameObject which has already been returned to the pool manager.

maxPoolSize
This will be the max size of the stack, the created pooled GameObjects should never exceed this size.

pool
Collection of all the IObectPools. We will be using the name of the prefabs as id for the pooled GameObjects.

IsReady
Check if pool manager is ready for use.

OnCleanup
Callback when the pool manager is going to be destroyed. Pooled GameObjects should be returned to the pool and destroyed as well.

OnRelease
Callback when pool manager is going to release all pooled GameObjects. The GameObjects do not get destroyed at this point, they are just returned to the pool and get disabled.

So far so good! Crack your knuckles because we’ll be diving into the functions next.

InstantiatePool
CreateObjectsPool allocates the necessary stack collection per GameObject and InitializeObjectsPool gets the GameObject in stack and initializes it. Once that’s done, we release the GameObjects back to pool so that they are ready to be used.

In doing so, we are preloading all the required assets, to avoid the need to create new GameObjects during the actual game play.

Note that OnRelease is called at the end. Remember our collection is a stack: if we were to do this immediately after initialising the GameObject, we’re essentially just getting the same GameObject we released previously.

CleanupPool
Destroys the pooled GameObjects and releases the memory.

ReleasePooledObject
Returns all pooled GameObjects back to the pool manager. No memory is freed at this point. This just puts the GameObject back into the pool where it’s ready for the next time we need it.

CreateObjectsPool
Here we create the ObjectPool using Unity Pool API. We’ll be using the GameObject name as an id to spawn the GameObject. At this point there’s no actual GameObject creation.

Initialisation of the pool requires 4 callbacks, which we will go through in a moment.

CreatePooledItem
Actual GameObject creation. Here we’re adding another component PooledGameObject which be use for lifetime management.

OnGetFromPool
All GameObjects which are in the pool are disabled, so when we get an instance of the GameObject we need to enable it.

OnReleaseToPool
Returning the GameObject back to the pool.

OnDestroyPoolObject
When pool gets destroyed we want to clean up the allocated GameObjects as well.

InitializeObjectsPool
In CreateObjectsPool we don’t actually create any GameObjects. It will be fine if we only need 1 or 2 instance of the GameObject each time. However what happens if we need to spawn a large number of GameObjects? We’ll still see that unwanted pause from the first time of instantiating and initialising of the GameObject.

To avoid this, we’ll create the GameObjects in advance and set it aside in the pool to be used.

I hope I’ve not lost you so far in the deep end of the pool.

Pooled GameObject

We have our pool collection, where we can create and initialise the pooled GameObjects, but we need to be able to return the GameObject once we’re done with it.

This will be handled by the PooledGameObject itself. On calling OnRelease the PooledGameObject will return itself back to the pool collection.

Spawning A Pooled GameObject

So far we’ve created our pool collection, instantiating and initialising the pooled GameObjects and allowing to return itself back to the pool. But how do we actually get a pooled GameObject?

Let’s go back to PoolManager.cs and add the missing function called Spawn.

Here, we’ll look for the correct pool collection based on our spawn id and return a pooled GameObject.

Tying It All Together

  • Create a pool manager GameObject
  • Create a prefab and add it to the pool manager and set the pool count accordingly.
    You should see something similar to the following:
  • Setup the following bootstrap to initialize the pool manager and get 2 GameObjects from the pool.
  • Hit play in editor and you should see the a cube and sphere (they should be overlapping at the origin at this point) in scene and under the PoolManager GameObject some disabled cube and spheres which have been created according to our pool item setup.

There we have it, a simple pool system which uses Unity pool API for memory management. I hope this will give you a quick start on how to setup object pooling for your next project.

If you’re interested in how to setup a spawning system with editor support, feel free to pop over to my mini series on Spawn Doctor: part 1 and part 2. Don’t forget to follow Mighty Bear Games on Medium for more articles like this, and drop me some claps if you found this article helpful!

--

--