Design Patterns in Unity3D #3 - Object Pool
Game development involves a lot of object creation & destruction process. For example, a Tower Defense game will continuously spawn the enemy creeps until the wave ends or the player died, and a creep will be destroyed when its health is zero.
Object creation/destruction is an expensive task to do. Doing it frequently, especially when the game is running, will hurt the performance of the game significantly. So are there any way that we could create many objects without continuously creating it in Update?
Yes there is. Enter the Object Pool pattern. The intent of this pattern is to spawn all the objects in the initialization process and then put those objects in a "pool", and if you want to use one of those object, just simply activate it and remove it from that pool. Later, if the object won't be used anymore, simply return it back to the pool without destroying it.
Let's see the how the Object Pool pattern works in Unity3D.
First, create an empty object, and create a C# script called Object Pool.
We will treat the Object Pool class as a singleton. So create a private static instance of it and in void Awake, initialize it with this, and after that create a public static getter for the singleton instance.
Now we are in the main part. Create a List of GameObject. This will represent all the objects that are in the pool.
Create a new method registerObject() with a GameObject parameter. This function will basically create the object, registering it to the pool, and then put it to inactive, and the parameter will be the prefab that will be spawned.
Notice that in the end we return the spawned object. This is because we want to keep the reference of the spawned object , so that later when we want to activate that object, we simply give that reference. I'll give you an illustration. Imagine when you want to put your stuff in a public storage, and you will be given a certain number, which tells you in which rack/slot is your stuff being stored. It is similar to Object Pool. So the reference acts similar to the number from the illustration, it corresponds to the object that is stored, so when we want to activate the object later on, we can just simply give the reference and the object pool will activate the object.
Next, create a method activateObject() which has a GameObject parameter. This parameter, once again, will be the reference object that will be passed to the method to activate the object that corresponds to that reference. But first we need to check whether the object exists. If it is, then set the object to active, and remove it from the pool. Remember, when we activate the object, it is the same as taking away the object from the pool.
We will do the opposite action when we want to deactivate objects. So when the object is no longer useful, we will return it back to the pool and deactivate it.
This is the full code for Object Pool.cs :
Now that we have the object pool, the next thing will be creating an spawner object that can spawn something. The spawner will later interact with the object pool in terms of storing the spawned object into it. In this case, let's make an Arsenal class, that can spawn missile. The missile will be stored in the object pool in the beginning of the scene and can be activated whenever you want during the update.
In the Arsenal class, we need to specify how much missiles we want to be spawned, so create a constant integer NUM_OF_MISSILES. For this tutorial, We'll set it to 20. Then we need the reference to the object pool and the missile prefab. we want to spawn it every one second so we make a WaitForSecond object and set it to 1 second. We declare a list of missiles, and that is basically the list of missile references corresponding to the missile that is being stored in the object pool.
In the Start function, we do all the required initialization, including the WaitForSecond and ObjectPool object initialization. Next, we will register all the missiles that we want to spawn into the ObjectPool. Then we will store the reference of the stored missile given from ObjectPool into a List of GameObject.
Then, create a SpawnMissile coroutine, and in there we will loop through those missile references in the List and we will activate the missiles using each of those references. The counter variable helps us to keep track on which index in the list are we currently, and once the index reaches the maximum number of elements, we will reset it back to zero.
This is the full code of Arsenal.cs :
Lastly, we will create another C# script, which is the script for the Missile. The missile in this tutorial, will have 2 seconds of lifetime. So in this class we will make a timer variable to count, as well as the object pool instance, and then once the timer reaches 2, this object will deactivate itself and return itself back to the pool.
We now finished the coding part. Now let's go back to the Unity Editor. Create two objects, the first one is an empty object, its the arsenal, and the second one is a sphere, which is the missile. Now attach the Arsenal and Missile scripts to their respective game objects.
Next, drag the missile to the prefab, and delete it from the hierarchy. Then in the Arsenal, assign the missile prefab to it.
Now click play. It will show that we created 20 missile objects in the beginning, deactivate it, and then every second after that we activate them one by one, and once we reached the 2oth missile, the next missile that is going to be spawned is the 1st missile. The missile itself will deactivate and register itself back to the pool after 2 seconds (remember it has 2 seconds lifetime).
So that is the tutorial about how to implement Object Pool pattern in Unity3D. Hope this helps. Thank you.