135 lines
3.7 KiB
C#
135 lines
3.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace GuruClient
|
|
{
|
|
public class GameObjectPool
|
|
{
|
|
private int _capacity = 10;
|
|
private GameObject _prefab;
|
|
private Transform _root;
|
|
private Stack<GameObject> _cache;
|
|
private Dictionary<int, GameObject> _activeObj;
|
|
private List<GameObject> _tmpList;
|
|
private Action<GameObject> _onInit;
|
|
private Action<GameObject> _onRecycle;
|
|
|
|
public static GameObjectPool CreatePool(GameObject prefab, int capacity = 10, bool isPreLoad = false)
|
|
{
|
|
GameObjectPool pool = new GameObjectPool();
|
|
pool._prefab = prefab;
|
|
pool._capacity = capacity;
|
|
pool._cache = new Stack<GameObject>(capacity);
|
|
pool._tmpList = new List<GameObject>();
|
|
pool._activeObj = new Dictionary<int, GameObject>();
|
|
pool._root = new GameObject(prefab.name + " [Pool]").transform;
|
|
// pool._root.DontDestroyOnLoad(pool._root);
|
|
pool._root.gameObject.SetActive(false);
|
|
if (isPreLoad)
|
|
{
|
|
PreLoad(pool);
|
|
}
|
|
return pool;
|
|
}
|
|
|
|
private static void PreLoad(GameObjectPool pool, bool worldPositionStays = true)
|
|
{
|
|
for (int i = 0; i < pool._capacity; i++)
|
|
{
|
|
GameObject obj = GameObject.Instantiate(pool._prefab);
|
|
obj.transform.SetParent(pool._root, worldPositionStays);
|
|
}
|
|
}
|
|
|
|
private GameObjectPool() {}
|
|
|
|
public void OnInit(Action<GameObject> action)
|
|
{
|
|
_onInit = action;
|
|
}
|
|
|
|
public void OnRecycle(Action<GameObject> action)
|
|
{
|
|
_onRecycle = action;
|
|
}
|
|
|
|
public GameObject GetObj(Transform parent = null, bool worldPositionStays = true)
|
|
{
|
|
GameObject obj = null;
|
|
if (_cache.Count <= 0)
|
|
{
|
|
obj = GameObject.Instantiate(_prefab);
|
|
}
|
|
else
|
|
{
|
|
obj = _cache.Pop();
|
|
if (obj == null)
|
|
{
|
|
obj = GameObject.Instantiate(_prefab);
|
|
}
|
|
}
|
|
|
|
int hash = obj.GetHashCode();
|
|
_activeObj[hash] = obj;
|
|
|
|
obj.transform.SetParent(parent, worldPositionStays);
|
|
if (!obj.activeSelf)
|
|
{
|
|
obj.SetActive(true);
|
|
}
|
|
obj.transform.localScale=Vector3.one;
|
|
_onInit?.Invoke(obj);
|
|
return obj;
|
|
}
|
|
|
|
public bool RecycleObj(GameObject obj)
|
|
{
|
|
if (obj == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
int hash = obj.GetHashCode();
|
|
if (_activeObj.ContainsKey(hash))
|
|
{
|
|
_activeObj.Remove(hash);
|
|
}
|
|
if (_cache.Count < _capacity)
|
|
{
|
|
_onRecycle?.Invoke(obj);
|
|
_cache.Push(obj);
|
|
obj.transform.SetParent(_root);
|
|
return true;
|
|
}
|
|
|
|
GameObject.Destroy(obj);
|
|
return false;
|
|
}
|
|
|
|
public void RecycleAll()
|
|
{
|
|
foreach (var kv in _activeObj)
|
|
{
|
|
_tmpList.Add(kv.Value);
|
|
}
|
|
|
|
foreach (GameObject obj in _tmpList)
|
|
{
|
|
if (!RecycleObj(obj))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
_activeObj.Clear();
|
|
_tmpList.Clear();
|
|
}
|
|
|
|
public void Destroy()
|
|
{
|
|
GameObject.Destroy(_root.gameObject);
|
|
_cache.Clear();
|
|
}
|
|
}
|
|
} |