对象池模式,本质就是循环利用对象,需要使用时从池子里拿出来,不需要使用时放入到池子里而不是直接删除。
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);
}
}