初学者,自用笔记

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();
        }
    }
}

待优化-单例等使用依赖注入