Object Pooling in the Gamekit

Checked with version: 2017.3

-

Difficulty: Beginner

The Game Kit uses an extensible object pooling system for some of its systems. The following explanation is only relevant to those wishing to extend the system for their own use and is not required knowledge for working with the Game Kit.

In order to extend the object pool system you must create two classes - one which inherits from ObjectPool and the other from PoolObject. The class inheriting from ObjectPool is the pool itself while the class inheriting from PoolObject is a wrapper for each prefab in the pool. The two classes are linked by generic types. The ObjectPool and PoolObject must have the same two generic types: the class that inherits from ObjectPool and the class that inherits from PoolObject in that order. This is most easily shown with an example:

public class SpaceshipPool: ObjectPool

{

}

public class Spaceship: PoolObject

{

}

This is so that the pool knows the type of objects it contains and the objects know what type of pool to which they belong. These classes can optionally have a third generic type. This is only required if you wish to have a parameter for the PoolObject’s WakeUp function which is called when the PoolObject is taken from the pool. For example, when our spaceships are woken up, they might need to know how much fuel they have and so could have an additional float type as follows:

public class SpaceshipPool: ObjectPool

{

}

public class Spaceship: PoolObject

{

}

By default a PoolObject has the following fields:

  • inPool: This bool determines whether or not the PoolObject is currently in the pool or is awake.

  • instance: This GameObject is the instantiated prefab that this PoolObject wraps.

  • objectPool: This is the object pool to which this PoolObject belongs. It has the same type as the ObjectPool type of this class.

A PoolObject also has the following virtual functions:

  • SetReferences: This is called once when the PoolObject is first created. Its purpose is to cache references so that they do not need to be gathered whenever the PoolObject is awoken, although it can be used for any other one-time setup.

  • WakeUp: This is called whenever the PoolObject is awoken and gathered from the pool. Its purpose is to do any setup required every time the PoolObject is used. If the classes are given a third generic parameter then WakeUp can be called with a parameter of that type.

  • Sleep: This is called whenever the PoolObject is returned to the pool. Its purpose is to perform any tidy up that is required after the PoolObject has been used.

  • ReturnToPool: By default this simply returns the PoolObject to the pool but it can be overridden if additional functionality is required.

An ObjectPool is a MonoBehaviour and can therefore be added to GameObjects. By default it has the following fields:

  • Prefab: This is a reference to the prefab that is instantiated multiple times to create the pool.

  • InitialPoolCount: The number of PoolObjects that are created in the Start method.

  • Pool: A list of the PoolObjects.

An ObjectPool also has the following functions:

  • Start: This is where the initial pool creation happens. You should note that if you have a Start function in your ObjectPool it effectively hides the base class version.

  • CreateNewPoolObject: This is called when PoolObjects are created and calls their SetReferences and then Sleep functions. It is not virtual, so it cannot be overridden but it is protected and can therefore be called in your inheriting class if you wish.

  • Pop: This is called to get a PoolObject from the pool. By default it searches for the first one that has the inPool flag set to true and return that. If none are true it creates a new one and returns that. It calls WakeUp on whichever PoolObject is going to be returned. This is virtual and can be overridden.

  • Push: This is called to put a PoolObject back in the pool. By default it just sets the inPool flag and calls Sleep on the PoolObject but it is virtual and can be overridden.

For a full example of how to use the object pool system, see the BulletPool documentation and scripts.

BulletPool

The BulletPool MonoBehaviour is a pool of BulletObjects, each of which wraps an instance of a bullet prefab. The BulletPool is used for both Ellen and enemies but is used slightly differently for each. For Ellen there is a BulletPool MonoBehaviour attached to the parent GameObject with the Bullet prefab set as its Prefab field. The other use of BulletPool is in the EnemyBehaviour class. It uses the GetObjectPool static function to use BulletPools without the need to actively create them.

The BulletPool class has the following fields:

  • Prefab: This is the bullet prefab you wish to use.

  • Initial Pool Count: This is how many bullets are created in the pool to start with. It should be as many as you expect to be used at once. If more are required they are created at runtime.

  • Pool: This is the BulletObjects in the pool. This is not shown in the inspector.

The BulletPool class has the following functions:

  • Pop: Use this to get one of the BulletObjects from the pool.

  • Push: Use this to put a BulletObject back into the pool.

  • GetObjectPool: This is a static function that finds an appropriate BulletPool given a specific prefab.

When getting a bullet from the pool it comes in the form of a BulletObject. The BulletObject class has the following fields:

  • InPool: Whether or not this particular bullet is in the pool or being used.

  • Instance: The instantiated prefab.

  • ObjectPool: A reference to the BulletPool this BulletObject belongs to.

  • Transform: A reference to the Transform component of the instance.

  • Rigidbody2D: A reference to the Rigidbody2D component of the instance.

  • SpriteRenderer: A reference to the SpriteRenderer component of the instance.

  • Bullet: A reference to the Bullet script of the instance.

The BulletObject has the following functions:

  • WakeUp: This is called by the BulletPool when its Pop function is called.

  • Sleep: This is called by the BulletPool when its Push function is called.

  • ReturnToPool: This should be called when you are finished with a particular bullet. It calls the Push function of its BulletPool and so calls its Sleep function.

Related tutorials