unity_art_puzzle_playable_luna/APPlayableLuna/Assets/Scripts/GameObjectPool.cs

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