Unity泛型对象池(逻辑层和表现层)

目标:希望对不同的类对象都能创建相对应的逻辑对象池。

一、类模板

/// <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();
    }
}

二、对象池管理单例

说明:负责管理对象池的创建以及销毁

首先定义一个单例模板:

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;
        }
    }
}

定义对象池管理单例

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);
        }
    }
}

三、使用说明

将Test脚本挂载在空物体上

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>();//销毁对象池
    }
}

结果:

补充:假如我想实现点击鼠标自动在游戏场景中实例化出来游戏物体的对象池该怎么办呢?

这时候需要单独去写个对GameObject做处理的对象池

GameObjectPool脚本

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脚本

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);
    }
}

预览效果如下

猜你喜欢

转载自blog.csdn.net/ysn11111/article/details/128920377
今日推荐