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