为什么使用对象池
当一个游戏需要频繁的创建和销毁对象时,为了不增加GC的性能消耗,可以考虑使用回收对象来打到复用的目的。(适用于飞机大战类,消除类,射击类,moba类等游戏)
什么是对象池
为了回收和复用对象,我们使用一个集合来存储不使用的对象,当需要使用该对象时,再从集合中取出,这样一个工具类称之为对象池。
对象池的实现
ObjectPool:对存储对象的集合进行了适当的封装,用于单个游戏对象(预制体)的回收和复用。
PoolManager:对ObjectPool单个游戏对象的进一步封装,可以用于创建多个对象(预制体)的回收和复用,可以更方便的使用对象池。(对象池模块化)
IPoolRelease:对象池回收对象时的还原接口,继承后对象自动还原初始值。
代码
using UnityEngine;
using System.Collections.Generic;
/// <summary>
/// 对象池
/// </summary>
public class ObjectPool {
private GameObject prefab;
private Stack<GameObject> pool = new Stack<GameObject>();
public ObjectPool(GameObject _prefab)
{
prefab = _prefab;
}
//取对象
public GameObject Get()
{
if (pool.Count > 0)
{
GameObject go = pool.Pop();
go.SetActive(true);
return go;
}
else
{
GameObject go = GameObject.Instantiate(prefab);
return go;
}
}
//回收,存对象
public void Save(GameObject go)
{
go.transform.SetParent(PoolManager.Instance.transform);
go.SetActive(false);
//调用回收对象的重置方法,(接口中定义)
IPoolRelease ipool = go.GetComponent<IPoolRelease >();
if(ipool!=null)
{
ipool.OnReset();
}
pool.Push(go);
}
}
using UnityEngine;
using System.Collections.Generic;
/// <summary>
/// 1.有且只有一个唯一的实例
/// 2.只能自己赋值,别人不能修改(私有的构造)
/// </summary>
public class PoolManager : MonoBehaviour {
//私有的静态实例
private static PoolManager _instance = null;
//懒汉式 单例模式
//共有的唯一的,全局访问点
public static PoolManager Instance
{
get
{
if (_instance == null)
{
_instance = GameObject.FindObjectOfType<PoolManager>();
if (_instance == null)
{
GameObject go = new GameObject("PoolManager");
_instance = go.AddComponent<PoolManager>();
}
}
return _instance;
}
}
public GameObject[] prePrefabs;
//饿汉式 单例模式
private void Awake()
{
if (_instance == null)
_instance = this;
else
Destroy(gameObject);
InitPool();
}
private Dictionary<string, ObjectPool> dic = new Dictionary<string, ObjectPool>();
void InitPool()
{
//提前初始化的对象池
foreach (var prefab in prePrefabs)
{
CreatPool(prefab.name, prefab);
}
}
/// <summary>
/// 创建对象池
/// </summary>
/// <param name="poolName">对象池名字</param>
/// <param name="prefab">对象池对应的预制体</param>
public void CreatPool(string poolName,GameObject prefab)
{
if (!dic.ContainsKey(poolName))
{
dic[poolName] = new ObjectPool(prefab);
}
}
/// <summary>
/// 获取对象池对象
/// </summary>
/// <param name="poolName">对象池名字</param>
/// <returns></returns>
public GameObject Get(string poolName)
{
ObjectPool pool;
if(dic.TryGetValue(poolName,out pool))
{
return pool.Get();
}
else
{
Debug.LogError("对象池:" + poolName + " 不存在!!!");
return null;
}
}
/// <summary>
/// 回收对象
/// </summary>
/// <param name="poolName">对象池的名字</param>
/// <param name="go">对象</param>
public void Save(string poolName,GameObject go)
{
ObjectPool pool;
if (dic.TryGetValue(poolName, out pool))
{
pool.Save(go);
}
else
{
Debug.LogError("对象池:" + poolName + " 不存在!!!");
}
}
}
public interface IPoolRelease {
void OnReset();
}
网友评论