對象池
一種通用型的技術,在其他語言中也會用到
- 池
線程池、網絡連接池,池是一個思想,將不用的東西暫時用池存起來,等到再次使用的時候再調出來用,節省CPU的調度
- 對象
C#的任何一個類都可以實例化一個對象Object
Unity中的遊戲對象GameObject
- 思路
最開始的時候,池中沒有對象,需要生成。用完之後放到池中。再次使用的時候再從池中獲取
3.1 回收對象
把對象放到池中
3.2 獲取對象
從池中獲取對象
3.3 代碼實現
using System.Collections.Generic;
using UnityEngine;
public class ObjectPool
{
region 單例
// 聲明單例
private static ObjectPool Instance;
///
/// 獲取單例
///
/// The instance.
/// Res path.
public static ObjectPool GetInstance(string resPath = "")
{
if (Instance == null)
{
if (resPath != "")
Instance = new ObjectPool(resPath);
else
Instance = new ObjectPool();
}
Instance.UpdateResourcePath(resPath);
return Instance;
}
// 構造函數
private ObjectPool()
{
prefabs = new Dictionary();
pools = new Dictionary>();
}
private ObjectPool(string resPath)
{
prefabs = new Dictionary();
pools = new Dictionary>();
resourcePath = resPath;
}
endregion
region 對象預設體資源管理
// 資源加載路徑
private string resourcePath;
// 用字典存儲所有的預設體
private Dictionary prefabs;
// 更新預設體加載路徑
private void UpdateResourcePath(string resPath)
{
resourcePath = resPath;
}
// 獲取預設體
private GameObject GetPrefab(string prefabName)
{
// 如果包含預設體,直接返回
if (prefabs.ContainsKey(prefabName))
return prefabs[prefabName];
// 如果不包含預設體,添加新的預設體,並返回
return LoadPrefab(prefabName);
}
// 加載預設體
private GameObject LoadPrefab(string prefabName)
{
// 拼接路徑
string path = "";
if (resourcePath != "")
{
path += resourcePath;
}
// 加載預設體
GameObject obj = Resources.Load(path + prefabName);
// 存入字典
if (obj != null)
prefabs.Add(prefabName, obj);
// 返回
return obj;
}
endregion
region 對象池
// 對象池
private Dictionary> pools;
///
/// 回收對象
///
/// Object.
public void RecycleObject(GameObject obj)
{
// 非激活
obj.SetActive(false);
// 獲取對象名稱
string objName = obj.name.Replace("(Clone)", "");
// 判斷有無該類對象池
// 如果沒有,實例化一個子池
if (!pools.ContainsKey(objName))
pools.Add(objName, new List());
// 存入
pools[objName].Add(obj);
}
///
/// 獲取對象
///
/// The object.
/// Object name.
/// Pool event.
public GameObject SpawnObject(string objName, System.Action poolEvent = null)
{
// 聲明一個輸出結果
GameObject result = null;
// 如果有池,並且池中有對象
if (pools.ContainsKey(objName) && pools[objName].Count > 0)
{
result = poolsobjName;
pools[objName].Remove(result);
}
// 如果沒有池,或者池中沒有對象,需要生成
else
{
// 拿到預設體
GameObject prefab = GetPrefab(objName);
if (prefab != null)
result = GameObject.Instantiate(prefab);
}
// 激活
result.SetActive(true);
// 執行事件
if (result && poolEvent != null)
poolEvent(result);
// 返回結果
return result;
}
endregion
}