Object pooling is a design pattern mainly used for preventing continuous creation and destruction of a type of object — in other terms, recycling the objects. By using object pooling, we prevent unnecessary garbage allocation in the memory resulting that a new frame will not be waiting for completion of garbage collection of the previous frame.
The idea is pretty simple: a pool of an object is created; which returns an object within the pool according to requests. Once the duty of the object is over, it’s moved back to the pool rather than being destroyed.
Certainly, constant creation and destruction of objects cause garbage collection. Object pooling design pattern is a great optimization in terms of eliminating the garbage collection caused by instantiation and destruction of same type of game objects.
The finest example for this case is the bullets used in the games.
In the case in which we are not using object pooling design pattern, each time we press the fire button, a new bullet game object would be instantiated; which would be again destroyed after some time or once hit on a game object. Imagine the memory load of a multiplayer game in which tens of enemies are shooting at the same time. And of course, the garbage collection.
I have created a basic cube that fires basic capsules. Each time I fire a bullet, 72B of garbage was allocation within the memory.
Despite 72B is a low value, imagine the case of instantiating tens-hundreds of bullets in a few seconds.
Long story short: If there’s a need for creating and destroying many game objects in a short amount of time, object pooling design pattern comes to the rescue. The objects within the pool are being instantiated at the initial run. Rather than being destroyed and recreated, they are just being moved within the application/game according to the requests.
Implementation of Object Pooling
As we want to reuse and recycle the game objects, the idea of object pooling is pulling the game objects from a data set on the time of need — rather than instantiation-, and sending them back to the pool — rather than destruction.
Here’s the initial script:
And of course, bullet was destroyed after some seconds of creation.
To handle the object pooling duties, I have created a Pool Manager game object with a PoolManager script. Of course, as it is a manager class, I have used Singleton design pattern. A list will be created to store the bullets available to be used by the player. These bullets will lie in an inactive state while they are not in use. Once the Player requests a bullet, he will search for an inactive bullet in the bullet list and gather the available one by changing its position and setting it’s state to active. Lastly, after the player is done with a particular bullet, we need to make sure that it returns to the list to be used again.
First, we need to create a list:
Then, the player needs to have an access to the bullet: as the bullet position will be determined by the player’s position. Thus, the pool manager needs to return a bullet once the player asks for a bullet.
Certainly, it wouldn’t make sense to make the player wait if there are no bullets left in the pool. Thus, it’s better to add to functionality to instantiate new bullets to be added to the list if the initial bullet list is not enough.
The newly created bullets will be available again to be used by the player once they are recycled. Recycling the game object back again is pretty easy: Just make it inactive.
Once you play the game, you will realize that the bullets will be returned back to the pool to be used again.
As you can see below, I have initally created a pool of 10 bullets. As I was spamming the keyboard, it instantiated 2 more bullets.