此对象池主要针对游戏资源,希望对大家有所帮助!
对象池的使用,例如:缓存消除游戏用的砖块
第一步:初始化池子
ObjectPoolManager.Instance.CreatePool(StringDefine.SpritePoolName, 120, 200,
ResManager.Instance.LoadAsset<GameObject>(StringDefine.CellName, (int)ResManager.eResType.Model), (int)ObjectPoolManager.ePoolType.Sprite);
第二步:从池子中获取对象
GameObject go = ObjectPoolManager.Instance.Get(StringDefine.SpritePoolName);
第三步:将不用的对象放回池子
ObjectPoolManager.Instance.Recycle(StringDefine.SpritePoolName, destroyObject);
(注:SingletonMono是一个Mono的单例,就不在这里放入了)
using UnityEngine;
using System.Collections.Generic;
namespace NTFrame
{
/// <summary>
/// 对象池管理器
/// </summary>
public class ObjectPoolManager : SingletonMono<ObjectPoolManager> {
public enum ePoolType
{
GameObject = 0,
Sprite = 1,
}
private Transform mPoolRootObject = null;
private Dictionary<string, GameObjectPool> mGameObjectPools = new Dictionary<string, GameObjectPool>();
Transform PoolRootObject {
get {
if (mPoolRootObject == null) {
var objectPool = new GameObject("ObjectPool");
objectPool.transform.SetParent(transform);
objectPool.transform.localScale = Vector3.one;
objectPool.transform.localPosition = Vector3.zero;
mPoolRootObject = objectPool.transform;
}
return mPoolRootObject;
}
}
public GameObjectPool CreatePool(string poolName, int initSize, int maxSize, GameObject prefab, int poolType = (int)ePoolType.GameObject) {
var poolInfo = new PoolInfo(poolName, prefab, initSize, maxSize);
return CreatePool(poolInfo, poolType);
}
public GameObjectPool CreatePool(PoolInfo poolInfo, int poolType = (int)ePoolType.GameObject)
{
if (mGameObjectPools.ContainsKey(poolInfo.poolName))
{
Debug.LogError("创建过此对象池:" + poolInfo.poolName);
return null;
}
var pool = CreateObjectPool(poolInfo, poolType);
if(pool == null)
{
Debug.LogError("poolType 错误!无法创建对应的对象池");
return null;
}
mGameObjectPools.Add(poolInfo.poolName, pool);
return pool;
}
GameObjectPool CreateObjectPool(PoolInfo poolInfo, int poolTy)
{
ePoolType poolType = (ePoolType)poolTy;
switch (poolType)
{
case ePoolType.GameObject:
return new GameObjectPool(poolInfo, PoolRootObject);
case ePoolType.Sprite:
return new SpritePool(poolInfo, PoolRootObject);
}
return null;
}
public GameObject Get(string poolName) {
GameObjectPool pool = GetGameObjectPool(poolName);
if(pool == null)
{
Debug.LogError("Invalid pool name specified: " + poolName);
return null;
}
return pool.NextAvailableObject();
}
GameObjectPool GetGameObjectPool(string poolName)
{
GameObjectPool pool = null;
mGameObjectPools.TryGetValue(poolName, out pool);
return pool;
}
public void Recycle(string poolName, GameObject go) {
GameObjectPool pool = GetGameObjectPool(poolName);
if(pool == null)
{
Debug.LogWarning("No pool available with name: " + poolName);
return;
}
pool.ReturnObjectToPool(poolName, go);
}
public void DestroyGameObjectPool(string poolName)
{
GameObjectPool pool = null;
if(mGameObjectPools.TryGetValue(poolName, out pool))
{
pool.DoDestroy();
mGameObjectPools.Remove(poolName);
}
}
}
}
using UnityEngine;
using System.Collections.Generic;
namespace NTFrame {
public class PoolInfo {
public string poolName;
public GameObject poolObjectPrefab;
public int poolSize;
public int maxSize;
public PoolInfo(string poolName, GameObject poolObjectPrefab, int poolSize, int maxSize)
{
this.poolName = poolName;
this.poolObjectPrefab = poolObjectPrefab;
this.poolSize = poolSize;
this.maxSize = maxSize;
}
}
/// <summary>
/// 资源对象池基类
/// </summary>
public class GameObjectPool {
protected PoolInfo mPoolInfo;
protected Transform mPoolRoot;
protected Queue<GameObject> mAvailableObjQueue = new Queue<GameObject>();
public GameObjectPool(PoolInfo poolInfo, Transform root)
{
mPoolInfo = poolInfo;
mPoolRoot = root;
InitPool();
}
protected void InitPool()
{
for (int index = 0; index < mPoolInfo.poolSize; index++)
{
AddObjectToPool(NewObjectInstance());
}
}
protected void AddObjectToPool(GameObject go) {
go.SetActive(false);
mAvailableObjQueue.Enqueue(go);
go.transform.SetParent(mPoolRoot);
}
protected GameObject NewObjectInstance() {
return GameObject.Instantiate(mPoolInfo.poolObjectPrefab) as GameObject;
}
public GameObject NextAvailableObject() {
GameObject go = null;
if(mAvailableObjQueue.Count > 0)
{
go = mAvailableObjQueue.Dequeue();
}
else
{
// TODO:正常情况应该是足够的,如果对象池里不够了,实例化一个新的
go = NewObjectInstance();
}
go.SetActive(true);
return go;
}
public virtual void ReturnObjectToPool(string pool, GameObject po) {
if (mPoolInfo.poolName.Equals(pool)) {
AddObjectToPool(po);
} else {
Debug.LogError(string.Format("Recycle to incorrect pool {0} ", mPoolInfo.poolName));
}
}
public void DoDestroy()
{
while (mAvailableObjQueue.Count > 0)
{
GameObject go = mAvailableObjQueue.Dequeue();
GameObject.Destroy(go);
go = null;
}
mPoolInfo.poolObjectPrefab = null;
mPoolInfo = null;
}
}
}
using UnityEngine;
namespace NTFrame
{
/// <summary>
/// 2d精灵对象池
/// </summary>
public class SpritePool : GameObjectPool
{
public SpritePool(PoolInfo poolInfo, Transform root) : base(poolInfo, root)
{
}
public override void ReturnObjectToPool(string pool, GameObject po)
{
if (mPoolInfo.poolName.Equals(pool))
{
var sprite = po.GetComponent<SpriteRenderer>();
if (sprite != null)
{
sprite.sprite = null;
sprite.sortingLayerName = "Default";
sprite.sortingOrder = 0;
GameObject.Destroy(po.GetComponent<Item>());
}
AddObjectToPool(po);
}
}
}
}