Pool System Using Unity 2021+
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?
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
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
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 object which is used for instantiating the pooled object.
The number of pooled GameObjects to be created.
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.
Remember the PoolItem earlier on? We can use this to set a default count value for it.
Collection of the pool item data which will be used to create the pooled GameObjects.
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.
This will be the max size of the stack, the created pooled GameObjects should never exceed this size.
Collection of all the IObectPools. We will be using the name of the prefabs as id for the pooled GameObjects.
Check if pool manager is ready for use.
Callback when the pool manager is going to be destroyed. Pooled GameObjects should be returned to the pool and destroyed as well.
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.
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.
Destroys the pooled GameObjects and releases the memory.
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.
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.
Actual GameObject creation. Here we’re adding another component PooledGameObject which be use for lifetime management.
All GameObjects which are in the pool are disabled, so when we get an instance of the GameObject we need to enable it.
Returning the GameObject back to the pool.
When pool gets destroyed we want to clean up the allocated GameObjects as well.
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.
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!