1.Mono单例类的编写
因为对象池是唯一的,并且需要挂载到场景,所以用到单例模式
/// <summary>
/// Mono单例类
/// </summary>
/// <typeparam name="T"></typeparam>
public class MonoSingleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T _singleton;
public static T SingleTon
{
get
{
if (_singleton == null)
{
_singleton = FindObjectOfType<T>();
if (_singleton == null)
{
Debug.LogError("场景中未找到类的对象,类名为:" + typeof(T).Name+"该类可能没有挂载到场景中");
}
}
return _singleton;
}
}
private void Awake()
{
if (_singleton == null)
{
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
}
2.对象池的编写
直接上代码
基于Dotween的对象池,不需要使用的去掉对应部分就可以了
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
using System;
using UnityEngine.LowLevel;
using UnityEngine.InputSystem;
public class ObjectPool : Single<ObjectPool>
{
private Dictionary<string, List<GameObject>> pool = new Dictionary<string, List<GameObject>>();//对象池
private Dictionary<string, GameObject> parentRoot = new Dictionary<string, GameObject>();//对象池游戏场景对应key服务提
private Dictionary<GameObject,string> gameObjKey=new Dictionary<GameObject,string>();//保存对象的key
private ObjectPool()
{
//私有构造方法
}
/// <summary>
/// 初始化
/// </summary>
/// <param name="gameObj"></param>
private void InitObjectPool(GameObject gameObj,Transform parent=null)
{
if (pool.ContainsKey(gameObj.name))
{
Debug.LogError("对应键" + gameObj.name + "该对象池已经存在");
return;
}
pool.Add(gameObj.name, new List<GameObject>());//��ʼ��
if(parent != null)
{
parentRoot.Add(gameObj.name,parent.gameObject);
}
else
{
parentRoot.Add(gameObj.name, new GameObject(gameObj.name));
}
GameObject game1 = Instantiate(parentRoot[gameObj.name], transform.position, Quaternion.identity, transform);
game1.SetActive(false);
Init(gameObj.name, game1);
GameObject game = Instantiate(gameObj, transform.position, Quaternion.identity, pool[gameObj.name][0].transform);
Init(gameObj.name, game);
}
private void InitObjectPool(string key, GameObject gameObj,Transform parent=null)
{
if (pool.ContainsKey(key))
{
Debug.LogError("对应键" + key + "该对象池已经存在");
return;
}
pool.Add(key, new List<GameObject>());
if (parent != null)
{
parentRoot.Add(key, parent.gameObject);
}
else
{
parentRoot.Add(key, new GameObject(gameObj.name));
}
//初始化根节点
GameObject game = Instantiate(parentRoot[key], transform.position, Quaternion.identity, transform);
game.SetActive(false);
Init(key, game);
//实例化第一个
GameObject game1 = Instantiate(gameObj, transform.position, Quaternion.identity, pool[key][0].transform);
Init(key, game1);
}
/// <summary>
/// 初始化
/// </summary>
/// <param name="key"></param>
/// <param name="gameObj"></param>
private void Init(string key, GameObject gameObj)
{
if (pool[key].Count == 0)
{
Debug.Log(key);
gameObj.name = key;
}
else
{
gameObj.name = key + pool[key].Count;
}
gameObjKey.Add(gameObj, key);
pool[key].Add(gameObj);
}
/// <summary>
/// 回收
/// </summary>
/// <param name="key">对象池key</param>
/// <param name="gameObj"></param>
public void Recycle(GameObject gameObj)
{
string key;
if (gameObjKey.ContainsKey(gameObj))
{
key = gameObjKey[gameObj];
gameObj.transform.SetParent(pool[key][0].transform);
//杀死或者暂停sequence 序列
gameObj.transform.DOKill(gameObj.transform);
gameObj.SetActive(false);
}
else
{
Print.printd("该对像非对象池创建,无法回收");
Print.printd(gameObj);
Debug.LogError("对应键:" + "对象池不存在");
}
}
/// <summary>
/// 创建对象池并获取
/// </summary>
/// <param name="gameObj">对象模板</param>
/// <param name="transfor">创建位置</param>
/// <param name="action">设置行为</param>
/// <returns></returns>
public GameObject GetGameObject(GameObject gameObj, Vector3 posi = default, Transform parent = null, Action<GameObject> action=null)
{
Debug.Log("123" + IsExistence(gameObj.name)+" "+ gameObj.name);
if (!IsExistence(gameObj.name))
{
InitObjectPool(gameObj,parent);
}
string key= gameObj.name;
if (pool.ContainsKey(key))
{
if (pool[key].Count <=2)
{
GameObject game = Instantiate(pool[key][1], transform.position, Quaternion.identity, pool[key][0].transform);
game.name = key + pool[key].Count;
pool[key].Add(game);
gameObjKey.Add(game, key);
}
int i = pool[key].Count - 1;
pool[key][i].transform.SetParent(parentRoot[key].transform);
if (parent != null)
{
pool[key][i].transform.SetParent(parent);
}
action?.Invoke(pool[key][i]);
pool[key][i].SetActive(true);
if (posi != null)
{
pool[key][i].transform.position = posi;
}
GameObject go = pool[key][i];
pool[key].RemoveAt(i);
return go;
}
else
{
Debug.LogError("该" + key + "对象池不存在");
return null;
}
}
/// <summary>
/// 根据key创建对象池并获取
/// </summary>
/// <param name="key">键</param>
/// <param name="gameObj">对象模板</param>
/// <param name="posi">创建位置</param>
/// <param name="parent">设置父物体</param>
/// <param name="action">设置行为</param>
/// <returns></returns>
public GameObject GetGameObject(string key, GameObject gameObj, Vector3 posi = default, Transform parent = null, Action<GameObject> action = null)
{
if (!IsExistence(gameObj.name))
{
InitObjectPool(key, gameObj,parent);
}
if (pool.ContainsKey(key))
{
if (pool[key].Count <= 2)
{
GameObject game = Instantiate(pool[key][1], transform.position, Quaternion.identity, pool[key][0].transform);
game.name = key + pool[key].Count;
pool[key].Add(game);
gameObjKey.Add(game, key);
}
int i = pool[key].Count - 1;
pool[key][i].transform.SetParent(parentRoot[key].transform);
if(parent != null)
{
pool[key][i].transform.SetParent(parent);
}
action?.Invoke(pool[key][i]);
pool[key][i].SetActive(true);
if (posi != null)
{
pool[key][i].transform.position= posi;
}
GameObject go = pool[key][i];
pool[key].RemoveAt(i);
return go;
}
else
{
Debug.LogError("该" + key + "对象池不存在");
return null;
}
}
/// <summary>
/// 检查对象池是否存在
/// </summary>
/// <param name="key">对象池不存在key</param>
/// <returns></returns>
public bool IsExistence(string key)
{
if (pool.ContainsKey(key))
return true;
else
return false;
}
/// <summary>
/// 清除所有对象池
/// </summary>
public void CleaAll()
{
foreach (string key in pool.Keys)
{
pool[key].Clear();
}
}
/// <summary>
/// 清除一个对象池
/// </summary>
/// <param name="key">对象key</param>
public void CleaOne(string key)
{
if (pool.ContainsKey(key))
{
pool[key].Clear();
}
else
{
Debug.LogError("该" + key + "对象池不存在");
}
}
/// <summary>
/// 删除所有对象池
/// </summary>
public void ResetPool()
{
pool.Clear();
}
}
2.1从对象池获取对象
GameObject go = pool.GetGameObject(bullite, transform.position,null, (gameObj) =>
{
Sequence seq=DOTween.Sequence();
seq.AppendCallback(() =>
{
if((gameObj.transform.position - transform.position).magnitude>100) {
pool.Recycle(gameObj);
}
}).AppendInterval(0.1f).SetLoops(-1);
});
参数分别对应要获取的对象,位置,父物体,行为(委托)
2.2回收对象
pool.Recycle(gameObj)
是的你没看错,非常的简单。