UnityVR--PoolManager--Object Pool 2

Table of contents

foreword

Basic structure of object pool and manager

Object pool code Chunk.cs

Object pool manager code ChunkAllocator.cs

use

Summarize


foreword

After the understanding of the object pool 1   in the previous article , the ObjectPool that comes with Unity has been used for memory optimization. This article builds an object pool manager (Manager) to realize functions such as object pool creation, deletion, and resource loading. This is not superfluous, because in the process of defining the object pool manager, you can understand the general structure of a script of the Manager class, and then write a lot of Managers.

Basic structure of object pool and manager

    Establish an object pool manager (allocator), because there may be multiple object pools in the scene at the same time, and a manager is needed to manage methods such as taking objects out of the pool and recycling objects. That is, the object pool manager is a toolset that includes general methods for object pool operations.

    The overall structure of the object pool management design is shown in the figure below. There is a general manager (ChunkAllocator), which is a manager (Manager), so it is a singleton mode (that is, there is only one instance on the field); create a dictionary in ChunkAllocator ( Dictionary<kew,value>) is used to store all object pools (Chunk), and each object pool (Chunk) has a list List<T> to store all objects.

 

     In the manager (ChunkAllocator) and object pool (Chunk), the tool methods used in the following scenarios are established:

  

Object pool code Chunk.cs

   For the management of a single object pool (imagine the Trophy object pool in the previous article), the functions that need to be implemented: 1. Create an object list; 2. Take an object; 3. Eliminate an object;  

public class Chunk
{
    List<Object> objectList; //建立一个列表,作为对象池的容器
	public bool IsHave => objectList.Count > 0; //判断列表中有没有对象
    //当IsHave为True时才能使用GetObj()调取对象
  
	public Chunk()
	{//构造中先初始化容器(列表)
        objectList = new List<Object>();
	}

	public Object GetObj()
	{//从容器(列表)中取出对象
		Object obj = objectList[objectList.Count - 1]; //取出第一个对象
		objectList.RemoveAt(objectList.Count - 1);  //容器(列表)中移除这个被取出的对象
		return obj;
	}

	public void RevertObj(Object obj)
	{//回收对象到容器(列表)
		(obj as GameObject).transform.parent= null;  //将对象父节点设为空
        (obj as GameObject).SetActive(false);  //将对象失活
		objectList.Add(obj);  //最后添加回容器(列表)中
    }
}

Object pool manager code ChunkAllocator.cs

  Manager Manager code inherits singleton (all management classes are single). Functions realized by the object pool manager: 1. Create an object pool dictionary; 2. Determine whether the object pool already exists; 3. Obtain an object from the object pool and load it into the scene; 4. Add an object to the object pool through the resource manager object, and load it into the scene; 5. Empty the object pool

  *Note: 1. Resload (loading resources from the Asset folder), Single (single instance) and other classes used here will be explained in a separate space later, these are the basic classes in a project;

  2. The method is not comprehensive enough, it is only a test reference.

//对象池分配器,单例
public class ChunkAllocator : Single<ChunkAllocator> 
{
    Dictionary<string, Chunk> chunkList; //定义一个字典存储所有的对象池

    public ChunkAllocator()
    {//构造中先实例化字典
        chunkList = new Dictionary<string, Chunk>();
    }

    private bool IsHavePool(string poolName)
    {//用对象池的名字查询是否已存在
        return chunkList.ContainsKey(poolName);
    }

    //获取对象
    public Object GetObject(string poolName)
    {//判断池子是否存在
        if (!IsHavePool(poolName))
        {
            return new Object();//不存在就直接实例化一个Object
        }
        return chunkList[poolName].GetObj(); //存在则通过名字找到它,并拿取对象
    }

    //回收对象到池中
    public void Revert(string poolName,Object obj)
    {
        if(IsHavePool(poolName))  //先判断对象池是否存在
        {
            chunkList[poolName].RevertObj(obj); //如果存在就直接回收进池
        }
        else
        {
            Chunk chunk= new Chunk(); //没有对应的对象池则先新建一个
            chunk.RevertObj(obj);     //再用新对象池回收该对象
            chunkList.Add(poolName, chunk);  //并把这个新对象池加入到字典中
        }
    }

    //直接从对象池中获取对象
    public GameObject GetGameObject(string poolName,GameObject gameObj,out bool isFirst,Transform parent=null)
    {//(对象池名称,对象,是否第一次创建,父节点)
        GameObject go = null;
        if(!IsHavePool(poolName))  //先判断对象池是否存在
        {//对象池不存在
            go = GameObject.Instantiate(gameObj); //实例化一个物体
            isFirst=true;  //将“第一次创建”的标记设为True
        }
        else
        {//对象池已存在
            isFirst = !chunkList[poolName].IsHave;  //池内有物体,就把“第一次创建”设false
            if (chunkList[poolName].IsHave)
            {
                go = chunkList[poolName].GetObj() as GameObject;//池内有物体就获取它
            }
            else
            {
                go = GameObject.Instantiate(gameObj); //池内没有物体就实例化一个
            }
        }
        if(parent != null)
        {//如果有父节点的要求,就将物体设置到父节点下
            go.transform.SetParent(parent);
        }
        go.transform.localScale = Vector3.one;  //设置物体大小
        go.transform.position = Vector3.zero;   //位置
        go.name= poolName;                      //名字
        go.SetActive(true);   //激活物体

        return go;  //返回物体
    }

    //从资源管理器中获取资源对象
    public T GetObj<T>(string poolName,string resName) where T : Object
    {
        if (!IsHavePool(poolName))
        {//如果对象池不存在,就用Resload加载Asset文件夹中的对象
            return Resload.Instance.LoadAsset<T>(resName);
        }
        return chunkList[poolName].GetObj() as T; //如果对象池存在,则直接调取对象
    }

    //从资源管理器中获取预制体
    public GameObject GetPrefab(string poolName,string resName,Transform parent=null)
    {
        GameObject go = null;
        if (!IsHavePool(poolName))
        {//如果对象池不存在,就用Resload加载
            go = Resload.Instance.LoadPrefab(resName);
        }
        else
        {//如果有对象池,先判断对象池中是否有东西
            if (chunkList[poolName].IsHave)
                go = chunkList[poolName].GetObj() as GameObject;//如果有,就从池中获取
            else
                go = Resload.Instance.LoadPrefab(resName);//否则就通过路径加载
        }
        if(parent!=null)
        {//设置父节点
            go.transform.SetParent(parent);
        }
        go.transform.localScale = Vector3.one;
        go.transform.position = Vector3.zero;
        go.SetActive(true);
        go.name = poolName;
        return go;
    }

    //清空对象池
    public void ClearPool(string poolName="")
    {
        if(poolName=="")
        {
            chunkList.Clear();
            return;
        }
        if(IsHavePool(poolName))
        {
            chunkList.Remove(poolName);  //如果对象池已存在,就清除
        }
    }
}

use

    We still use the Trophy in the previous article, the scene structure remains unchanged, only TrophyManager.cs is modified

using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Pool;

public class TrophyManager : MonoBehaviour
{
    public GameObject[] trophies;
    public int number = 50;
    public bool useObjectPool;
    public bool useChunkAllocator;
    private ObjectPool<GameObject> trophyPool;

    void Start()
    {

    }

    void Update()
    {
        for (int i = 0; i < number; i++)
        {
            bool isfirst = false;
            GameObject trophy = ChunkAllocator.Instance.GetGameObject("trophyPool", trophies[Random.Range(0, trophies.Length)], out isfirst, transform);
            trophy.transform.localPosition = Random.insideUnitSphere;
            trophy.AddComponent<Trophy>();
            if (isfirst)
            {
                trophy.GetComponent<Trophy>().destroyEvent.AddListener(() =>
                {
                    ChunkAllocator.Instance.Revert("trophyPool", trophy);
                });
            }
        }

Summarize

  It can be seen that the manager Manager is a collection of methods, that is, put some commonly used methods into a class. Moreover, there are many ways to implement this manager, and different tools and methods are added according to the needs of different projects, but this idea and structure are common to projects established later.

Guess you like

Origin blog.csdn.net/tangjieitc/article/details/130754359