# 对象池
- 作用:将物体放到一个集合中,可以循环利用
- 适用性:适合频繁生成和销毁的物体,比如:子弹、技能、特效......
- 对象池只有一个,所以使用单例模式
- 循环利用时需要做初始化,不同的物体有不同的初始化方法,所以使用接口
代码如下:
namespace Common | |
{ | |
// 可重置的 | |
public interface IResettable | |
{ | |
void OnReset(); | |
} | |
/// <summary> | |
/// 对象池 | |
/// </summary> | |
public class ObjectPool : MonoSingleton<ObjectPool> | |
{ | |
private Dictionary<string, List<GameObject>> GameObjectDIC; | |
protected override void Init() | |
{ | |
base.Init(); | |
GameObjectDIC = new Dictionary<string, List<GameObject>>(); | |
} | |
/// <summary> | |
/// 获取物体 | |
/// </summary> | |
/// <param name="gameObjectKey"> 物体类型 & lt;/param> | |
/// <param name="prefab"> 预制件 & lt;/param> | |
/// <param name="position"> 位置 & lt;/param> | |
/// <param name="rotation"> 旋转 & lt;/param> | |
/// <returns></returns> | |
public GameObject GetGameObject(string gameObjectKey, GameObject prefab, Vector3 position, Quaternion rotation) | |
{ | |
GameObject temp; | |
if (!GameObjectDIC.ContainsKey(gameObjectKey)) | |
{ | |
GameObjectDIC.Add(gameObjectKey, new List<GameObject>()); | |
} | |
// 生成物体 | |
if ((temp = GameObjectDIC[gameObjectKey].Find(g => !g.activeInHierarchy)) == null) | |
{ | |
temp = Instantiate(prefab); | |
GameObjectDIC[gameObjectKey].Add(temp); | |
} | |
// 设置参数 | |
SetParameters(temp, position, rotation); | |
return temp; | |
} | |
/// <summary> | |
/// 设置参数 | |
/// </summary> | |
/// <param name="gameObject"></param> | |
/// <param name="position"></param> | |
/// <param name="rotation"></param> | |
private void SetParameters(GameObject gameObject, Vector3 position, Quaternion rotation) | |
{ | |
gameObject.transform.position = position; | |
gameObject.transform.rotation = rotation; | |
// 遍历物体中所有需要重置的逻辑 | |
foreach (var item in gameObject.GetComponents<IResettable>()) | |
{ | |
item.OnReset(); | |
} | |
gameObject.SetActive(true); | |
} | |
/// <summary> | |
/// 回收物体 | |
/// </summary> | |
/// <param name="gameObjectKey"> 物体类型 & lt;/param> | |
/// <param name="gameObject"> 物体 & lt;/param> | |
public void RecoverGameObject(GameObject gameObject) | |
{ | |
gameObject.SetActive(false); | |
} | |
/// <summary> | |
/// 延迟回收物体 | |
/// 使用协程 | |
/// </summary> | |
/// <param name="gameObjectKey"> 物体类型 & lt;/param> | |
/// <param name="gameObject"> 物体 & lt;/param> | |
/// <param name="delay"> 延迟时间(秒)</param> | |
public void RecoverGameObject(GameObject gameObject, float delay) | |
{ | |
StartCoroutine(DelayRecover(gameObject, delay)); | |
} | |
/// <summary> | |
/// 延迟回收 | |
/// </summary> | |
/// <param name="gameObjectKey"></param> | |
/// <param name="gameObject"></param> | |
/// <param name="delay"></param> | |
/// <returns></returns> | |
private IEnumerator DelayRecover(GameObject gameObject, float delay) | |
{ | |
yield return new WaitForSeconds(delay); | |
gameObject.SetActive(false); | |
} | |
/// <summary> | |
/// 清空某一类别 | |
/// </summary> | |
/// <param name="gameObjectKey"></param> | |
public void Clear(string gameObjectKey) | |
{ | |
// 字典、队列等数据结构 存储的都是引用,这些都不占内存 | |
// 真正占内存的是生成的物体,所以主要目的是清除物体(主要是模型、网格、材质(各种贴图)、组件...) | |
//Destroy () 清除的就是这些真正占内存的物体 | |
foreach (GameObject item in GameObjectDIC[gameObjectKey]) | |
{ | |
GameObject.Destroy(item); | |
} | |
GameObjectDIC.Remove(gameObjectKey); | |
} | |
/// <summary> | |
/// 清空全部内容 | |
/// </summary> | |
public void ClearAll() | |
{ | |
//foreach 是只读的,如果直接用 GameObjectDIC.Keys 会报错, | |
// 因为在执行 Clear (key) 时 GameObjectDIC.Keys 发生了改变, | |
//MoveNext () 方法可能会出错 | |
foreach (string key in new List<string>(GameObjectDIC.Keys)) | |
{ | |
Clear(key); | |
} | |
GameObjectDIC.Clear(); | |
} | |
} | |
} |