【Unity】对象池设计

对象池模式,本质就是循环利用对象,需要使用时从池子里拿出来,不需要使用时放入到池子里而不是直接删除。

Unity开发中,经常会出现频繁地删除和创建物体的情况,对象池模式可以极大地提高性能。

网上关于对象池的设计也有很多,这里介绍一下我设计的对象池的特点:

1、采用泛型,可以创建不同类型的对象池。

2、可以自定义放入对象、拿出对象的回调。

3、实例化完全在对象池类中实现,方便快捷。

使用示例:

初始化对象池:


    public LineRenderer lineRenderer;
    public ObjectPool<LineRenderer> linePool;

    void Start()
    {
        //初始化一个LineRenderer的对象池
        linePool = new ObjectPool<LineRenderer>(
         lineRenderer,//用于实例化的预设体
         (o) => o.gameObject.SetActive(true), //拿出的回调
         (o) => o.gameObject.SetActive(false));//放入的回调
    }

拿出对象、放入对象:


        LineRenderer lr = linePool.TakeOutOneObject();//拿出
        linePool.PutInObject(lr);//放入

代码:

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

/// <summary>
/// 对象池
/// </summary>
/// <typeparam name="T"></typeparam>
public class ObjectPool<T> where T : Object
{
    List<T> activedObjects = new List<T>();
    List<T> objectsPool = new List<T>();
    T prefab;
    UnityAction<T> onTakeOutOneObject;
    UnityAction<T> onPutInOneObject;

    /// <summary>
    /// 
    /// </summary>
    /// <param name="prefab">用于实例化的预设体</param>
    /// <param name="onTakeOutOneObj">拿出一个实例的回调</param>
    /// <param name="onPutInOneObj">放入一个实例的回调</param>
    public ObjectPool(T prefab, UnityAction<T> onTakeOutOneObj = null, UnityAction<T> onPutInOneObj = null)
    {
        this.prefab = prefab;
        this.onTakeOutOneObject = onTakeOutOneObj;
        this.onPutInOneObject = onPutInOneObj;
    }
    /// <summary>
    /// 拿出一个对象
    /// </summary>
    /// <returns></returns>
    public T TakeOutOneObject()
    {
        return TakeOutOneObject(null);
    }
    /// <summary>
    /// 拿出一个对象并设置父物体
    /// </summary>
    /// <param name="parent">父物体</param>
    /// <returns></returns>
    public T TakeOutOneObject(Transform parent)
    {
        T obj;
        if (objectsPool.Count > 0)
        {
            obj = objectsPool[0];
            objectsPool.RemoveAt(0);
        }
        else
        {
            obj = InstantiateObject(parent);
        }
        activedObjects.Add(obj);
        if (onTakeOutOneObject != null)
        {
            onTakeOutOneObject(obj);
        }
        return obj;
    }
    public void PutInObject(T obj)
    {
        if (activedObjects.Contains(obj))
        {
            activedObjects.Remove(obj);
            objectsPool.Add(obj);
            if (onPutInOneObject != null)
            {
                onPutInOneObject(obj);
            }
        }
    }
    public void ClearAllActivedObjects()
    {
        while (activedObjects.Count > 0)
        {
            PutInObject(activedObjects[0]);
        }
    }
    public T[] GetActivedObjects()
    {
        return activedObjects.ToArray();
    }
    T InstantiateObject(Transform parent)
    {
        if (parent != null)
        {
            return Object.Instantiate(prefab, parent);
        }
        return Object.Instantiate(prefab);
    }
}

猜你喜欢

转载自blog.csdn.net/b8566679/article/details/106219403
今日推荐