Object Pool - Malakahh/Unity-Tools GitHub Wiki
The purpose of an object pool is essentially enabling recycling of objects, and it is done for performance reasons, see https://en.wikipedia.org/wiki/Object_pool_pattern.
This object pool features async instantiation of objects given a threshold, and will grow by N*2, ensuring a readily available supply of objects. Furthermore, it follows the Singleton pattern.
Name | Parameters | Description |
---|---|---|
T Acquire<T>() where T : new() |
T: Type of object to acquire. | Acquires an object from the object pool. |
void Release<T>(T obj) |
T: Object type to release. obj: Object to release. | Releases an object back into the pool. |
void SetLowerInstantiationThreshold<T>(int threshold) |
T: Object type to set threshold for. threshold: The new lower threshold. | Sets the lower threshold for when instantiation of new objects should begin. Defaults to 1. If things are spawned often, i.e. bullets, you want to set this higher. |
int GetLowerInstatiationThreshold<T>() |
T: Object type to get threshold for. | Gets the lower threshold for when instatiation of new objects should begin. Defaults to 1. Returns -1 on fail. |
int GetInstanceCountTotal<T>() |
T: Object type. | Gets the total instance count of objects of a given type that exists, both in and out of the pool. |
Figure A | Figure B |
The initial setup is simple. Once imported into Unity, you should have a file tree similar to what can be seen in Figure A. To use the object pool, simply use the ObjectPool prefab in the scene, it will persist cross-scene, and reset itself accordingly, so it is only necessary to put it in the first scene.
Figure B shows the inspector view of ObjectPool. Error Level determines whether eventual exceptions should appear as regular exceptions, or show them in the console of Unity. Display warnings enables whether any warnings should be displayed in the console.
The object pool comes with some unit tests, if you wish to run these, make sure that Run Tests is enabled, otherwise turn it off in the inspector, or simply delete the Tests folder.
class Character : MonoBehaviour
{
void Awake()
{
//We need a lot of Bullets, so we need to make sure we have plenty available at all times.
//Once the object pool contains less than 10 bullets, we should start async instatiation of more,
//such as to keep up with demand.
ObjectPool.Instance.SetLowerInstantiationThreshold<Bullet>(10);
}
void Update()
{
//SHOOOT
Shoot();
}
void Shoot()
{
//Gets a bullet from the objectpool.
//If you want to use the object pool for something that inherits from UnityEngine.Object,
//these needs to be available in the Resources folder, and must be unique. In this case,
//there must only be one prefab in Resources with the script Bullet attached to it.
//Having multiple prefabs with the same scripts is undefined behavior.
//To avoid this, you can use inheritance, and specify, for instance, different kinds of ammunition.
Bullet b = ObjectPool.Instance.Acquire<Bullet>();
//Set Bullet position and trajectory
b.pos = transform.position;
b.dir = Vector2.up;
//Make sure that we show the Bullet. Any objects spawned from the objectpool will initially be inactive
b.gameObject.SetActive(true);
}
}
class Bullet : MonoBehaviour
{
public Vector2 pos;
public Vector2 dir;
void Update()
{
this.pos += dir;
}
void OnCollisionEnter(Collision collision)
{
//Do something to the target
ResetAndReturn();
}
void ResetAndReturn()
{
//Reset the bullet here, though no need to set active to false
//Return it to the object pool so that it may be recycled.
ObjectPool.Instance.Release<Bullet>(this);
}
}
Instantiate/acquire a number of objects, and destroy/return every second one. Run 10 tests, and average results.
Average time spent for 10,000 identical, simple GameObjects
Classic | Object Pooled |
---|---|
0.234788 | 0.135989 |
Here, the Object Pool completed the procedure 42.08% faster.