Unit object pool mode

1. Understand

The object pool is used to reduce memory overhead. Its principle is to store the objects that may be used in a place (pool) first, call them out when they need to be used, and put them back when they are not needed. Instead of creating it when you need it and destroying it when you don't need it.
Eg:
I have a plane to shoot bullets. The traditional method is to create bullets, hit the target or out of bounds, and destroy bullets. It is to create and destroy constantly. You should know that creation and destruction consume a lot of memory and time. If the bullet is stored in a place (pool), take it out when you need it and put it back when you don't need it.
  
If there are more than one aircraft, you can share a sub magazine.
Although this method has always maintained a maximum value of bullet storage space, it is very worth considering compared with the cost of continuous creation and destruction.
In actual development, the pool size can be appropriately enlarged or reduced as needed.
  
Object pool mode is not a unique design mode for game development. Its design idea is the same as that of database connection pool and thread pool in other development.

The core idea is not to delete it directly after use, but to put it back into the pool and take it out when necessary. The emergence of object pool mode mainly optimizes two points:

1. Prevent objects from being created and deleted frequently, resulting in memory jitter and frequent GC (garbage collection)

2. Object initialization costs are high

2. Operation

The following is a text introduction to the basic operation of the object pool

Borrowing: Generally speaking, it is to obtain objects from the pool. If you obtain objects for the first time, you should initialize the pool. If there is no desired object in the pool, create one

Return: Generally speaking, objects are to be deleted when they are used up, but after the object pool is applied, objects are returned to the pool on the premise that the number in the pool is not greater than the preset maximum number (to prevent too much memory explosion). If the number in the pool is greater than the preset maximum number, they are deleted directly

Preheating: preloading a certain number of objects. Personally, I think this is one of the more essential parts of the object pool. If preheating is not done, initialization is directly involved when creating objects for the first time. It's easy to understand that players would rather wait one second in the loading interface than get stuck for 0.1 seconds in the game, especially in competitive games, players will want to smash the computer (laugh). So I think if you don't do the object pool optimization of preheating, you only do half of it.

Shrink: it's almost like preheating. When returning, it says that if it is greater than the set quantity threshold, it will not be returned to the pool, but will be deleted directly. In fact, deletion may also bring time cost, so we can not delete it first, and then delete and shrink the memory pool every time we pass the loading interface in the middle of the game. If you are afraid that the memory will explode before loading the interface, you can set an additional threshold that must be deleted. Its function is the same as that written when returning it above. (I didn't do this function in my DEMO)

Reset: each newly taken object should be as "brand new" as the newly created one, and can not obviously have the last used state. Therefore, every time the object comes out of the pool, it should be reset where there may be aftereffects. In unity, the manual initialization of the object is written in OnEnable() of the object, including the force to empty the rigid body, etc. the difference between OnEnable() and Start() is that Start() only runs at the first frame when the object is enabled for the first time, and OnEnable runs every time the object is re enabled.

Object pool manager

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

/// <summary>
///Object pool manager
/// </summary>
public class PoolTest : MonoBehaviour
{
    /*
    The core of object pool is collection
    Make a collection with a stack
    public Stack<GameObject> stack = new Stack<GameObject>();
    You can also use list. It's relatively simple
    */
    public List<GameObject> list = new List<GameObject>();
    //Game prefab
    public GameObject GoPrefab;
    //Maximum number of objects in the object pool
    public int MaxCount=10;

    //Object into object pool
    public void Push(GameObject go)
    {
        //If the pool can still be filled, add it. If it is full, don't add it
        if (list.Count < MaxCount)
        {
            list.Add(go);
        }
        else
        {
            Destroy(go);
        }
    }

    //Take out the object from the object pool (the return value should be marked as GameObject)
    public GameObject Pop()
    {
        if (list.Count>0)//Judgment list is not empty
        {
            GameObject go = list[0];//If so, take out the first item
            list.RemoveAt(0);//Delete the first item in the list
            return go;
        }

        return Instantiate(GoPrefab);//If not, create a new preform directly
    }

    //Delete object pool
    public void Clear()
    {
        list.Clear();
    }
}

Test code

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

public class Test : MonoBehaviour
{
    //Used to manage preforms that are not stored in the object pool
    private List<GameObject> list = new List<GameObject>();

     void Update()
    {
        //create object
        if (Input.GetKeyDown(KeyCode.A))
        {
             GameObject go = GetComponent<PoolTest>().Pop();
             list.Add(go);
             go.SetActive(true);
        }
        //delete object
        if (Input.GetKeyDown(KeyCode.S))
        {
            if (list.Count>0)//Judge whether there are objects in the current scene
            {
                GetComponent<PoolTest>().Push(list[0]);
                list.RemoveAt(0);
                list[0].SetActive(false);
            }    
        }
    }

}

Hang two scripts on the same empty object
After running the project, we can clearly see that the preforms created are deleted by clicking the S key, not destroyed, but put into the object pool

Keywords: Unity

Added by JeanieTallis on Tue, 18 Jan 2022 04:16:08 +0200