Unity generic object pool (logic layer and presentation layer)

Goal: Hope to create corresponding logical object pools for different class objects.

1. Class template

/// <summary>
/// 逻辑层对象池模板,不包含GameObject类型
/// </summary>
/// <typeparam name="T"></typeparam>
public class ObjectPool<T> where T:class,new() 
{
    private Stack<T> pool = new Stack<T>();
    private int maxCount;//池子最大大小
    public ObjectPool(int maxCount)
    {
        this.maxCount = maxCount;
        //初始化池子容量为最大容量的1/2
        for (int i = 0; i < 0.5*maxCount; i++)
        {
            pool.Push(new T());
        }
    }

    /// <summary>
    /// 从池里面取类对象
    /// </summary>
    public T Spawn()
    {
        if (pool.Count > 0)
        {
            return pool.Pop();
        }
        else
        {
            return new T();
        }
    }

    /// <summary>
    /// 回收类对象
    /// </summary>
    public void Recycle(T obj)
    {
        if (pool.Count >= maxCount)
        {
            obj = null;
        }
        else
        {
            pool.Push(obj);
        }
    }

    public void ClearPool()
    {
        pool.Clear();
    }
}

2. Object pool management single instance

Description: Responsible for managing the creation and destruction of object pools

First define a singleton template:

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

// 实现普通的单例模式
// where 限制模板的类型, new()指的是这个类型必须要能被实例化
public abstract class Singleton<T> where T : new() {
    private static T _instance;
    private static object mutex = new object();
    public static T instance {
        get {
            if (_instance == null) {
                lock (mutex) { // 保证我们的单例,是线程安全的;
                    if (_instance == null) {
                        _instance = new T();
                    }
                }
            }
            return _instance;
        }
    }
}

Define object pool management singleton

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

public class ObjectPoolManager : Singleton<ObjectPoolManager>
{
    private Dictionary<Type, object> objectPools = new Dictionary<Type, object>();

    /// <summary>
    /// 生成对应类型的对象池
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="maxCount"></param>
    /// <returns></returns>
    public ObjectPool<T> GetObjectPool<T>(int maxCount) where T : class, new()
    {
        Type poolType = typeof(T);
        if (!objectPools.ContainsKey(poolType))
        {
            ObjectPool<T> pool = new ObjectPool<T>(maxCount);
            objectPools.Add(poolType, pool);
        }
        return objectPools[poolType] as ObjectPool<T>;
    }

    /// <summary>
    /// 销毁对象池
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public void DestroyObjectPool<T>() where T : class, new()
    {
        Type poolType = typeof(T);
        if (objectPools.ContainsKey(poolType)) {
            ObjectPool<T> pool = objectPools[poolType] as ObjectPool<T>;
            pool.ClearPool();
            objectPools.Remove(poolType);
        }
    }
}

3. Instructions for use

Mount the Test script on an empty object

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


public class Person{
    private int id;
    private string name="zidan";
    public void PrintName()
    {
        Debug.Log(name);
    }
}
public class Test : MonoBehaviour
{
    //创建一个最大容量为10的Person类对象池
    ObjectPool<Person> poolPerson = ObjectPoolManager.instance.GetObjectPool<Person>(10);
    private void Start()
    {
        Person person1=poolPerson.Spawn();//从Person对象池中取出元素
        person1.PrintName();
        ObjectPoolManager.instance.DestroyObjectPool<Person>();//销毁对象池
    }
}

result:

Supplement: What if I want to realize the object pool of game objects automatically instantiated in the game scene by clicking the mouse?

At this time, you need to write an object pool for GameObject processing

GameObjectPoolScript

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

public class GameObjectPool : MonoBehaviour
{
    private Stack<GameObject> pool = new Stack<GameObject>();
    private int maxCount;//池子最大大小
    private GameObject gamePrefab;//预制件
    public void InitPool(int maxCount,GameObject prefab)
    {
        GameObject go;
        this.maxCount = maxCount;
        gamePrefab = prefab;
        //初始化池子容量为最大容量的1/2
        for (int i = 0; i < 0.5 * maxCount; i++)
        {
            go = Instantiate(gamePrefab, this.transform);
            pool.Push(go);
            go.SetActive(false);
        }
    }

    /// <summary>
    /// 从池里面取类对象
    /// </summary>
    public GameObject Spawn()
    {
        if (pool.Count > 0)
        {
            GameObject go = pool.Pop();
            go.SetActive(true);
            return go;
        }
        else
        {
            return Instantiate(gamePrefab, this.transform);
        }
    }

    /// <summary>
    /// 回收类对象
    /// </summary>
    public void Recycle(GameObject go)
    {
        if (pool.Count >= maxCount)
        {
            Destroy(go.gameObject);
        }
        else
        {
            pool.Push(go);
            go.SetActive(false);
        }
    }

    public void ClearPool()
    {
        pool.Clear();
        Destroy(this.gameObject);
    }
}

Test script

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



public class Test : MonoBehaviour
{
    public GameObject pool;//场景中的一个空物体
    public GameObject prefab;//克隆对象
    private GameObjectPool poolScript;
    private void Start()
    {
        poolScript=pool.AddComponent<GameObjectPool>();
        poolScript.InitPool(6,prefab);
    }
    private void Update()
    {
        //按下鼠标左键就生成物体
        if (Input.GetMouseButtonDown(0))
        {
            GameObject cur=poolScript.Spawn();
            StartCoroutine(Recycle(cur));//物体5秒后自动被回收
        }
    }
    
    private IEnumerator Recycle(GameObject go)
    {
        yield return new WaitForSeconds(5);
        poolScript.Recycle(go);
    }
}

The preview effect is as follows

Guess you like

Origin blog.csdn.net/ysn11111/article/details/128920377