Behavioural Pattern.


Pattern explenation

Intent

Improve performance and memory use by reusing objects from a fixed pool instead of allocating and freeing them individually.

What it solve

Management of list of the same object type

Applications

  • To frequently create and destroy objects.
  • Objects are similar in size.
  • Allocating objects on the heap is slow or could lead to memory fragmentation.
  • Each object encapsulates a resource such as a database or network connection that is expensive to acquire and could be reused.

Actors

  • ObjectPool
    • Create the object
    • Store the objects that are ready to be reused
  • PooledObject
    • Notify ObjectPool about it’s status (is ready to be reused)
  • Client
    • Asks to ObjectPool the objects he need

Schema

Unity example

Client

Player.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{
    public ObjectPool myPool;

    void Start()
    {
        StartCoroutine(Firing());
    }

    IEnumerator Firing()
    {
        while (true)
        {
            GameObject go = myPool.TakeObject();
            go.transform.position = transform.position;
            yield return new WaitForSeconds(1f);
        }
    }
}

ObjectPool

ObjectPool.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ObjectPool : MonoBehaviour
{
    public Stack<PooledObject> pool;
    public GameObject prefab;

    private void Awake()
    {
        pool = new Stack<PooledObject>();
    }

    public GameObject TakeObject()
    {
        GameObject go;
        if(pool.Count == 0)
        {
            go = Instantiate(prefab, transform);
            PooledObject pooledObject = go.GetComponent<PooledObject>();
            pooledObject.Init(this);
        }
        else
        {
            go = pool.Pop().gameObject;
        }
        go.SetActive(true);
        return go;
    }

    public void GiveObject(PooledObject pooledObject)
    {
        pool.Push(pooledObject);
    }
}

PooledObject

PooledObject.cs

using UnityEngine;

public class PooledObject : MonoBehaviour
{
    private ObjectPool pool;
    public void Init(ObjectPool pool)
    {
        this.pool = pool;
    }

    private void OnDisable()
    {
        pool.GiveObject(this);
    }
}

Projectile.cs

using UnityEngine;

public class Projectile : PooledObject
{

    void Update()
    {
        transform.position += Vector3.right * 2 * Time.deltaTime;
    }

    private void OnTriggerEnter(Collider other)
    {
        gameObject.SetActive(false);
    }
}

Conclusion

Object Pool Pattern is always good to use when you need to spawn the same object multiple times (like projectiles) and it’s very easy to implement and it works well decoupled so don’t worry in big projects too!!