初学者,自用笔记
Unity官方对象池
对象池
// 定义对象池对象的行为接口
// 解耦对象池与具体对象的依赖
public interface IPoolable
{
void OnGet(); // 对象被获取时的初始化
//对象从池中取出时触发,用于重置对象状态(如子弹重置速度、敌人重置血量)
void OnGet<T>(T _data);// 带数据的获取,如敌人的等级,血量,结合敌人工厂使用
void OnRelease();// 对象被回收时的清理
//对象回收至池时触发,用于清理对象数据(如取消事件监听、重置位置)。
}
// 对象池管理类,单例模式
public class Pool : MonoBehaviour
{
[Header("池配置")]
public String key; // 池标识符
public GameObject prefab; // 池化预制体
public Transform poolParent; // 池对象父节点(用于层级管理)
public Vector3 defaultPosition; // 默认位置
public Vector3 defaultRotation; // 默认旋转(欧拉角)
public int initialSize = 10; // 初始容量
public int maxSize = 20; // 最大容量
public ObjectPool<PooledObjectBase> _objectPool;
public void Awake()
{
// 初始化对象池
_objectPool = new ObjectPool<PooledObjectBase>(
createFunc,
actionOnGet,
actionOnRelease,
actionOnDestroy,
collectionCheck: Application.isEditor, // 编辑器中开启检查
defaultCapacity: initialSize,
maxSize: maxSize
);
// 手动预热
for (int i = 0; i < initialSize; i++)
{
var obj = _objectPool.Get(); // 会调用 createFunc + actionOnGet
_objectPool.Release(obj); // 会调用 actionOnRelease
}
}
// 创建新对象
private PooledObjectBase createFunc()
{
GameObject obj = Instantiate(prefab, poolParent);
obj.transform.position = defaultPosition;
obj.transform.rotation = Quaternion.Euler(defaultRotation);
obj.SetActive(false);
PooledObjectBase pooledBase = obj.GetComponent<PooledObjectBase>();
if (pooledBase == null)
{
return null;
}
return pooledBase;
}
// 获取对象时的处理
private void actionOnGet(PooledObjectBase obj)
{
// 调用对象的自定义初始化
obj.OnGet();
obj.gameObject.SetActive(true);
}
// 回收对象时的处理
private void actionOnRelease(PooledObjectBase obj)
{
obj.gameObject.SetActive(false);
// 调用对象的自定义清理
obj.OnRelease();
}
// 销毁对象时的处理
private void actionOnDestroy(PooledObjectBase obj)
{
Destroy(obj);
}
// 外部接口:获取对象(默认位置)
public PooledObjectBase GetObject()
{
return _objectPool.Get();
}
// 外部接口:获取对象(指定位置和旋转)
public PooledObjectBase GetObject(Vector3 position, Quaternion rotation)
{
var obj = _objectPool.Get();
obj.transform.position = position;
obj.transform.rotation = rotation;
return obj;
}
public PooledObjectBase GetObject<TData>(TData data)
{
var obj = _objectPool.Get();
obj.OnGet(data);
return obj;
}
public PooledObjectBase GetObject<TData>(Vector3 position, Quaternion rotation, TData data)
{
var obj = _objectPool.Get();
obj.transform.position = position;
obj.transform.rotation = rotation;
obj.OnGet(data);
return obj;
}
// 外部接口:回收对象
public void ReleaseObject(PooledObjectBase obj)
{
if (obj == null) return;
_objectPool.Release(obj);
}
}
PoolManager
public class PoolManager : MonoBehaviour
{
public static PoolManager Instance;
public List<Pool> pools = new List<Pool>();
public Dictionary<string, Pool> poolDic = new Dictionary<string, Pool>();
private void Awake()
{
if (Instance == null)
{
Instance = this;
}
else
{
Destroy(gameObject);
}
InitAllPool();
}
// 初始化所有池
public void InitAllPool()
{
for (int i = 0; i < pools.Count; i++)
{
if (pools[i].prefab == null || string.IsNullOrEmpty(pools[i].key))
continue;
poolDic[pools[i].key] = pools[i];
}
}
public Pool CreatePool(string key, GameObject prefab, int initialSize = 10, int maxSize = 20,
Transform parent = null, Vector3 defaultPos = default, Vector3 defaultRot = default)
{
// 避免重复创建
if (poolDic.ContainsKey(key))
{
return poolDic[key];
}
// 创建池的载体GameObject(用于层级管理)
GameObject poolObj = new GameObject($"Pool_{key}");
//避免awake时还未赋值
poolObj.SetActive(false);
poolObj.transform.SetParent(transform); // 作为PoolManager的子节点
// 添加Pool组件并初始化配置
Pool newPool = poolObj.AddComponent<Pool>();
newPool.key = key;
newPool.prefab = prefab;
newPool.poolParent = parent ?? poolObj.transform;
newPool.defaultPosition = defaultPos;
newPool.defaultRotation = defaultRot;
newPool.initialSize = initialSize;
newPool.maxSize = maxSize;
AddPool(newPool);
//避免awake时还未赋值
poolObj.SetActive(true);
return newPool;
}
// 添加新池
public void AddPool(Pool _pool)
{
if (!poolDic.ContainsKey(_pool.key))
{
pools.Add(_pool);
poolDic[_pool.key] = _pool;
}
}
//外部接口:获取指定池的对象
public PooledObjectBase GetObject(string poolKey)
{
if (!poolDic.TryGetValue(poolKey, out Pool pool))
{
return null;
}
return pool.GetObject();
}
public PooledObjectBase GetObject(string poolKey, Vector3 position, Quaternion rotation)
{
if (!poolDic.TryGetValue(poolKey, out Pool pool))
{
return null;
}
return pool.GetObject(position, rotation);
}
// 带数据
public PooledObjectBase GetObject<TData>(string poolKey, TData data)
{
if (!poolDic.TryGetValue(poolKey, out Pool pool))
{
return null;
}
return pool.GetObject(data);
}
// 带位置 + 带数据
public PooledObjectBase GetObject<TData>(string poolKey, Vector3 position, Quaternion rotation, TData data)
{
if (!poolDic.TryGetValue(poolKey, out Pool pool))
{
return null;
}
return pool.GetObject(position, rotation, data);
}
public void ReleaseObject(string _key, PooledObjectBase _obj)
{
if (poolDic.TryGetValue(_key, out Pool pool))
{
pool.ReleaseObject(_obj);
}
}
public void ClearPool(string _key)
{
if(poolDic.TryGetValue(_key,out Pool pool))
{
pool._objectPool.Clear();
}
}
public void ClearAllPool()
{
for(int i=0;i<pools.Count;i++)
{
pools[i]._objectPool.Clear();
}
}
}
池对象基类
目的:缓存 IPoolable 引用,避免每次调用都GetComponent< IPoolable >
public abstract class PooledObjectBase : MonoBehaviour, IPoolable
{
// 实现IPoolable接口的抽象方法,强制子类重写
public abstract void OnGet();
public abstract void OnRelease();
}
运用实例
void Fire()
{
// 从对象池获取子弹
GameObject bullet = PoolManager.Instance.GetObject(
"Bullet",
firePoint.position,
firePoint.rotation
);
}
public class Bullet : PooledObjectBase
{
public float speed = 10f;
public float lifeTime = 3f;
private Rigidbody _rb;
protected override void Awake()
{
base.Awake(); // 调用父类Awake,确保缓存_poolable
_rb = GetComponent<Rigidbody>();
}
// 重写OnGet:子弹初始化逻辑
public override void OnGet()
{
_rb.velocity = transform.forward * speed;
Invoke(nameof(ReleaseSelf), lifeTime);
}
// 重写OnRelease:子弹清理逻辑
public override void OnRelease()
{
CancelInvoke(nameof(ReleaseSelf));
_rb.velocity = Vector3.zero;
}
// 碰撞检测(击中目标后回收)
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Enemy"))
{
// 击中敌人后立即回收
PoolManager.Instance.ReleaseObject("Bullet", gameObject);
}
}
}
官方对象池(泛型对象池)
对象池
public abstract class PoolBase : MonoBehaviour
{
[Header("池配置")]
public string key; // 池标识符
}
public class Pool<T> : PoolBase where T : PooledObjectBase
{
[Header("池配置")]
public T prefab; // 预制体(强类型)
public Transform poolParent; // 父节点
public Vector3 defaultPosition;
public Vector3 defaultRotation;
public int initialSize = 10;
public int maxSize = 20;
public ObjectPool<T> _objectPool;
private void Awake()
{
if (prefab == null)
{
Debug.LogError($"[Pool<{typeof(T).Name}>] Prefab is null, key={key}");
return;
}
_objectPool = new ObjectPool<T>(
createFunc,
actionOnGet,
actionOnRelease,
actionOnDestroy,
collectionCheck: Application.isEditor,
defaultCapacity: initialSize,
maxSize: maxSize
);
// 预热
for (int i = 0; i < initialSize; i++)
{
var obj = _objectPool.Get();
_objectPool.Release(obj);
}
}
private T createFunc()
{
T obj = Instantiate(prefab, poolParent);
obj.transform.position = defaultPosition;
obj.transform.rotation = Quaternion.Euler(defaultRotation);
obj.gameObject.SetActive(false);
return obj;
}
private void actionOnGet(T obj)
{
obj.OnGet();
obj.gameObject.SetActive(true);
}
private void actionOnRelease(T obj)
{
obj.gameObject.SetActive(false);
obj.OnRelease();
}
private void actionOnDestroy(T obj)
{
if (obj != null)
{
Destroy(obj.gameObject);
}
}
public T GetObject()
{
return _objectPool.Get();
}
public T GetObject(Vector3 position, Quaternion rotation)
{
var obj = _objectPool.Get();
obj.transform.position = position;
obj.transform.rotation = rotation;
return obj;
}
public T GetObject<TData>(TData data)
{
T obj = _objectPool.Get();
obj.OnGet(data);
return obj;
}
public T GetObject<TData>(Vector3 position, Quaternion rotation, TData data)
{
T obj = _objectPool.Get();
obj.transform.position = position;
obj.transform.rotation = rotation;
obj.OnGet(data);
return obj;
}
public void ReleaseObject(T obj)
{
if (obj == null) return;
_objectPool.Release(obj);
}
public void Clear()
{
_objectPool?.Clear();
}
}
PoolManager
public class PoolManager : MonoBehaviour
{
public static PoolManager Instance;
public List<PoolBase> pools = new List<PoolBase>();
public Dictionary<string, PoolBase> poolDic = new Dictionary<string, PoolBase>();
private void Awake()
{
if (Instance == null)
{
Instance = this;
}
else
{
Destroy(gameObject);
return;
}
InitAllPool();
}
// 初始化所有池
public void InitAllPool()
{
poolDic.Clear();
for (int i = 0; i < pools.Count; i++)
{
PoolBase pool = pools[i];
if (pool == null || string.IsNullOrEmpty(pool.key))
continue;
poolDic[pool.key] = pool;
}
}
public Pool<T> CreatePool<T>(
string key,
T prefab,
int initialSize = 10,
int maxSize = 20,
Transform parent = null,
Vector3 defaultPos = default,
Vector3 defaultRot = default
) where T : PooledObjectBase
{
// 避免重复创建
if (poolDic.TryGetValue(key, out PoolBase existing))
{
return existing as Pool<T>;
}
// 创建池的载体GameObject(用于层级管理)
GameObject poolObj = new GameObject($"Pool_{key}");
poolObj.SetActive(false);
poolObj.transform.SetParent(transform); // 作为PoolManager子节点
// 添加泛型Pool组件并初始化配置
Pool<T> newPool = poolObj.AddComponent<Pool<T>>();
newPool.key = key;
newPool.prefab = prefab;
newPool.poolParent = parent ?? poolObj.transform;
newPool.defaultPosition = defaultPos;
newPool.defaultRotation = defaultRot;
newPool.initialSize = initialSize;
newPool.maxSize = maxSize;
AddPool(newPool);
poolObj.SetActive(true);
return newPool;
}
// 添加新池
public void AddPool(PoolBase pool)
{
if (pool == null || string.IsNullOrEmpty(pool.key)) return;
if (!poolDic.ContainsKey(pool.key))
{
pools.Add(pool);
poolDic[pool.key] = pool;
}
}
// 获取指定池的对象(默认位置)
public T GetObject<T>(string poolKey) where T : PooledObjectBase
{
if (!poolDic.TryGetValue(poolKey, out PoolBase basePool))
{
return null;
}
if (basePool is Pool<T> pool)
{
return pool.GetObject();
}
return null;
}
// 获取指定池的对象(指定位置和旋转)
public T GetObject<T>(string poolKey, Vector3 position, Quaternion rotation) where T : PooledObjectBase
{
if (!poolDic.TryGetValue(poolKey, out PoolBase basePool))
{
return null;
}
if (basePool is Pool<T> pool)
{
return pool.GetObject(position, rotation);
}
return null;
}
//带数据
public T GetObject<T, TData>(string poolKey, TData data) where T : PooledObjectBase
{
if (!poolDic.TryGetValue(poolKey, out PoolBase basePool))
{
return null;
}
if (basePool is Pool<T> pool)
{
return pool.GetObject(data);
}
return null;
}
public T GetObject<T, TData>(string poolKey, Vector3 position, Quaternion rotation, TData data)
where T : PooledObjectBase
{
if (!poolDic.TryGetValue(poolKey, out PoolBase basePool))
{
return null;
}
if (basePool is Pool<T> pool)
{
return pool.GetObject(position, rotation, data);
}
return null;
}
public void ReleaseObject<T>(string poolKey, T obj) where T : PooledObjectBase
{
if (obj == null) return;
if (!poolDic.TryGetValue(poolKey, out PoolBase basePool))
{
return;
}
if (basePool is Pool<T> pool)
{
pool.ReleaseObject(obj);
}
}
public void ClearPool(string poolKey)
{
if (poolDic.TryGetValue(poolKey, out PoolBase pool))
{
pool.Clear();
}
}
public void ClearAllPool()
{
for (int i = 0; i < pools.Count; i++)
{
pools[i]?.Clear();
}
}
}

京公网安备 11010502036488号