Unity对象池

using System;
using System.Collections;
using System.Collections.Generic;
using JetBrains.Annotations;
using QFramework;
using UnityEngine;
using UnityEngine.SceneManagement;

/*
 * 对象池 默认分两个列表存放可见 和不可见 对象
 * 获取池对象时可见列表数未超出最大可见数时从不可见列表抽取实例显示
 * 超出时复用第一个可见对象
 */

[CreateAssetMenu(fileName = "XXPoolManager", menuName = "Scrpitable/PoolManager"), DefaultExecutionOrder(-500)]
public class PoolManager : ScriptableObject
{
    [SerializeField, Tooltip("set this if you want empty parent")]
    private Transform parentObj; //记录父布局

    [SerializeField] private GameObject prefab; //复用对象

    [SerializeField, Tooltip("recyclable limit count")]
    private int recyclePoolLimit = 30; //最大存放的可使用对象

    [SerializeField, Tooltip("active limit count")]
    private int activeCountLimit = 40; //最大可见数量 超出后复用第一个activite实例

    [SerializeField, Tooltip("if want cache on start")]
    private bool cacheOnStart = false; //是否在开始时进行缓存可用对象

    [SerializeField, Tooltip("cache count on start")]
    private int cacheCount = 10; //开始缓存的数量

    private List<GameObject> activeList; //存放可见已使用的对象
    private List<GameObject> recyclerList; //存放当前可使用的对象


    //根据下标获取可见的对象
    [CanBeNull]
    public GameObject this[int _index]
    {
        get
        {
            if (_index >= 0 && _index < activeList.Count)
            {
                return activeList[_index];
            }
            else
            {
                return null;
            }
        }
    }

    public int getActiveCount()
    {
        return activeList.Count;
    }

    public int getRecyclerCount()
    {
        return recyclerList.Count;
    }

    private void OnEnable()
    {
        activeList = new List<GameObject>();
        recyclerList = new List<GameObject>();
        SceneManager.activeSceneChanged += OnSceneSwitch;
    }

    private void OnDisable()
    {
        activeList.Clear();
        recyclerList.Clear();
        SceneManager.activeSceneChanged -= OnSceneSwitch;
    }


    //场景转换时
    private void OnSceneSwitch(Scene s, Scene s2)
    {
        ClearNullReferences();
        //是否开始时初始化部分可用实例
        if (cacheOnStart)
        {
            for (int i = 0; i < cacheCount - getActiveCount(); i++)
            {
                GameObject newObj = CreateNewPoolableObject(prefab.transform.position, prefab.transform.rotation);
                newObj.SetActive(false);
                recyclerList.Add(newObj);
            }
        }
    }

    //创建新的对象
    private GameObject CreateNewPoolableObject(Vector3 pos, Quaternion rotation)
    {
        GameObject createObj = null;
        if (parentObj == null)
        {
            createObj = Instantiate(prefab, pos, rotation);
        }
        else
        {
            createObj = Instantiate(prefab, pos, rotation, parentObj);
        }

        Poolable poolableComponent = createObj.AddComponent<Poolable>();
        poolableComponent.bindManager(this);
        return createObj;
    }

    //放回可复用列表
    public void RecyObj(Poolable _poolable)
    {
        if (recyclerList.Count > recyclePoolLimit)
        {
            Destroy(_poolable.gameObject);
            return;
        }

        recyclerList.Add(_poolable.gameObject);
        if (activeList.Contains(_poolable.gameObject))
        {
            activeList.Remove(_poolable.gameObject);
        }
    }

    //清空数据
    private void ClearNullReferences()
    {
        activeList = activeList.FindAll((obj) => { return obj != null; }); //!null
        recyclerList = recyclerList.FindAll((obj) => { return obj != null; }); //!null

        //释放所有
//        activeList.Clear();
//        recyclerList.Clear();
    }

    public GameObject Retrieve(Vector3 _pos, Quaternion _rotation)
    {
        if (getActiveCount() >= activeCountLimit)
        {
            GameObject obj = activeList[0];
            obj.SetActive(false);
            activeList.RemoveAt(0);
            activeList.Add(obj);
            obj.transform.position = _pos;
            obj.transform.rotation = _rotation;
            return obj;
        }

        if (getRecyclerCount() == 0)
        {
            GameObject obj1 = CreateNewPoolableObject(_pos, _rotation);
            activeList.Add(obj1);
            return obj1;
        }
        else
        {
            GameObject obj2 = null;

            foreach (var o in recyclerList)
            {
                if (o != null)
                {
                    obj2 = o;
                    break;
                }
            }

            if (obj2 != null)
            {
                ClearNullReferences();
                return Retrieve(_pos, _rotation);
            }

            recyclerList.Remove(obj2);
            activeList.Add(obj2);
            obj2.transform.position = _pos;
            obj2.transform.rotation = _rotation;
            return obj2;
        }
    }

    public T Retrieve<T>()
    {
        T getObject = Retrieve().GetComponent<T>();

        return getObject;
    }

    public GameObject Retrieve()
    {
        return Retrieve(prefab.transform.position, prefab.transform.rotation);
    }

    public void Retrieve(GameObject _targetSpawn)
    {
        parentObj = _targetSpawn.transform;
        Retrieve(_targetSpawn.transform.position, _targetSpawn.transform.rotation);
    }
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Poolable : MonoBehaviour
{
    private PoolManager _manager;

    //绑定对应的对象池
    public void bindManager(PoolManager manager)
    {
        _manager = manager;
    }

    private void OnDisable()
    {
        _manager.RecyObj(this);
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity 中的对象池是一种资源管理技术,用于在游戏运行过程中高效地创建、管理和回收对象。对象池的主要目的是减少频繁创建和销毁对象带来的性能开销,尤其是在有大量短期使用对象(如小敌人、项目等)的情况下。 下面是使用 Unity 对象池的基本步骤: 1. 创建对象池:首先,你需要创建一个包含所需对象类型的新对象池。这通常是一个静态类或专用脚本,负责管理对象的生命周期。 ```csharp public class ObjectPool<T> where T : Component { private List<T> poolObjects; private Stack<T> availableObjects; // 初始化方法 public ObjectPool(int initialSize) { poolObjects = new List<T>(); for (int i = 0; i < initialSize; i++) { T obj = Instantiate<T>(); obj.SetActive(false); // 设置对象为非活动状态,直到需要时才激活 poolObjects.Add(obj); } availableObjects = new Stack<T>(poolObjects); } // 获取对象 public T BorrowObject() { if (availableObjects.Count > 0) { T obj = availableObjects.Pop(); obj.SetActive(true); return obj; } else { T obj = Instantiate<T>(); return obj; } } // 归还对象 public void ReturnObject(T obj) { obj.SetActive(false); availableObjects.Push(obj); } } ``` 2. 使用对象池:当你需要一个新对象时,从池中借用一个,用完后记得归还。这样,当对象不再被使用时,它会被放回池而不是直接销毁,以便后续其他地方可能需要它。 ```csharp private ObjectPool<MyObject> objectPool; void Start() { objectPool = new ObjectPool<MyObject>(10); } void Update() { MyObject newObj = objectPool.BorrowObject(); // 使用 newObj ... newObj.gameObject.SetActive(false); // 当对象不再需要时,归还给池子 // 如果对象池已满,考虑创建更多对象 if (objectPool.availableObjects.Count == 0 && poolSize < MaxPoolSize) { // 添加新对象到池中 objectPool.poolObjects.Add(Instantiate<MyObject>()); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值