Not long ago, I released a small post on object pooling with a basic sample. That example was of a unity pooling system that was very un-opinionated, only requiring an interface. Today, I’m sharing another pooling system that’s similar but works a bit different. This system requires even less code to interact with, but does have one unique requirement.
This pooling system also has a few more options for usage available via overloads in the Get call that you’ll see soon.
Pooling gameobjects is essential for good performance. Instantiating a gameobject is slow and can impact performance significantly, especially if you do a bunch of it (like with bullets in a shooter). Pooling resolves this problem by re-using objects that are already instantiated and ready to go. And it’s easy to do!
Before I go into the details of how the pooling system works, I want to show some examples of how it’s used.
To get an object from this pooling system, all you need is a reference to the prefab and a single call to Get().
This pooling system actually has a variety of ways to get the pooled object to make it a bit more flexible.
The test class below shows a few of the different ways you can get an object along with a log entry of what it’s doing differently.
The Pooling System
To make this work, we need 2 common classes. We need the Pool class and the PooledMonoBehaviour class.
The Pool class handles organization of the pooled objects.
It is responsible for the following:
- Tracking which objects are available to be used
- Providing an object when one is requested (using Get())
- Instantiating and adding objects to the pool when needed
- Returning objects to the pool when they’re disabled.
The PooledMonobehaviour base class
The PooledMonobehaiour is a base class that any pooled objects need to inherit from. This is the one ‘requirement’ I mentioned at the beginning.
This class’s primary responsibility is calling the OnDestroyEvent when it’s disabled. That event tells our pooling system to re-add the object to the pool and is critical for the system to work.
But we also get some other benefits by using this base class.
First, we can define the default pool size on the prefab itself. There’s no special place to define the pool sizes, you just set it on each prefab individually as needed.
Additionally, the Get methods on the class allow us to get an instance with nothing other than a prefab reference.
Making a class poolable
To make a class poolable, inherit from PooledMonobehaviour like this.
What about Pre-warming?
If you’d like to pre-warm your object pools (which is often a good idea), this PoolPreparer will do the job.
To use it just drop the component on an empty gameobject and assign all the prefabs you want pre-warmed, it’ll do the rest.
There are countless different ways you can build a pooling system. Of the ways I’ve done it before though, this is one of my favorites. Primarily because usage only requires a prefab reference… This system as presented here is not setup for multi-scene scenarios though, so if you need your pools to persist across scenes, make sure to add that functionality.
Whatever you decide though, be sure to use some sort of pooling system when it makes sense. If you’re building a mobile game, it almost always makes sense… Or if you’re spawning 100’s of objects all the time, pooling them will help with performance..
And if you have a prefered pooling system of your own, be sure to share it in the comments! 🙂