268 lines
5.9 KiB
C#
268 lines
5.9 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using OHM.UnityToolkit;
|
|
|
|
namespace OHM.UnityToolkit.Pooling
|
|
{
|
|
public class PoolsManager : UniqueInstance<PoolsManager>
|
|
{
|
|
[SerializeField]
|
|
private Transform poolsContainer;
|
|
|
|
[SerializeField]
|
|
private List<PreloadPrefab> preloadPrefabs;
|
|
|
|
private Dictionary<int, Pool> pools;
|
|
|
|
public static T InstantiatePrefab<T>(T prefab, Transform parent, Vector3 position, Quaternion rotation, bool startActive = false) where T : Component
|
|
{
|
|
PooledObject pooledPrefab = prefab.GetComponent<PooledObject>();
|
|
if (pooledPrefab != null && Instance != null)
|
|
{
|
|
PooledObject instance = Instance.GetObjectFromPrefab(pooledPrefab, parent, position, rotation, startActive);
|
|
return (instance != null) ? instance.GetComponent<T>() : null;
|
|
}
|
|
|
|
T plain = UnityEngine.Object.Instantiate(prefab, position, rotation, parent);
|
|
plain.gameObject.SetActive(startActive);
|
|
return plain;
|
|
}
|
|
|
|
public static void ReleasePooledObject(PooledObject pooledObject)
|
|
{
|
|
if (pooledObject != null)
|
|
{
|
|
pooledObject.Release();
|
|
UnityEngine.Object.Destroy(pooledObject.gameObject);
|
|
}
|
|
}
|
|
|
|
public static void ReleaseObject(GameObject obj)
|
|
{
|
|
if (obj != null)
|
|
{
|
|
UnityEngine.Object.Destroy(obj);
|
|
}
|
|
}
|
|
|
|
public static IEnumerator DelayReleaseObject(GameObject go, float delay)
|
|
{
|
|
yield return new WaitForSeconds(delay);
|
|
ReleaseObject(go);
|
|
}
|
|
|
|
public static void ReleaseAllPooledChildren(Transform parent)
|
|
{
|
|
if (parent == null)
|
|
{
|
|
return;
|
|
}
|
|
PooledObject[] pooled = parent.GetComponentsInChildren<PooledObject>(true);
|
|
for (int i = 0; i < pooled.Length; i++)
|
|
{
|
|
ReleasePooledObject(pooled[i]);
|
|
}
|
|
}
|
|
|
|
protected override void AwakeInstance()
|
|
{
|
|
pools = new Dictionary<int, Pool>();
|
|
if (preloadPrefabs == null)
|
|
{
|
|
return;
|
|
}
|
|
foreach (PreloadPrefab preload in preloadPrefabs)
|
|
{
|
|
Pool pool = GetPoolFromPrefab(preload.prefab);
|
|
GrowPool(pool, preload.prefab, preload.preloadCount);
|
|
}
|
|
}
|
|
|
|
private int GetPrefabPoolId(PooledObject prefab)
|
|
{
|
|
return prefab.gameObject.GetInstanceID();
|
|
}
|
|
|
|
private Pool GetPoolFromPrefab(PooledObject prefab)
|
|
{
|
|
int id = GetPrefabPoolId(prefab);
|
|
Pool pool;
|
|
if (!pools.TryGetValue(id, out pool))
|
|
{
|
|
pool = new Pool();
|
|
pool.id = id;
|
|
pool.prefab = prefab;
|
|
pools[id] = pool;
|
|
}
|
|
return pool;
|
|
}
|
|
|
|
private Pool GetPoolId(int poolId)
|
|
{
|
|
Pool pool;
|
|
pools.TryGetValue(poolId, out pool);
|
|
return pool;
|
|
}
|
|
|
|
private PooledObject GetObjectFromPrefab(PooledObject prefab, Transform parent, Vector3 position, Quaternion rotation, bool startActive = false)
|
|
{
|
|
Pool pool = GetPoolFromPrefab(prefab);
|
|
PooledObject obj = null;
|
|
if (pool.freeObjects.Count >= 1)
|
|
{
|
|
obj = pool.freeObjects[pool.freeObjects.Count - 1];
|
|
pool.freeObjects.RemoveAt(pool.freeObjects.Count - 1);
|
|
pool.usedObjets.Add(obj);
|
|
obj.transform.SetParent(parent);
|
|
}
|
|
if (obj == null)
|
|
{
|
|
obj = InstantiateObjectForPool(pool, prefab, parent, startActive);
|
|
}
|
|
if (obj == null)
|
|
{
|
|
return null;
|
|
}
|
|
obj.transform.position = position;
|
|
obj.transform.rotation = rotation;
|
|
obj.gameObject.SetActive(startActive);
|
|
obj.Use();
|
|
return obj;
|
|
}
|
|
|
|
private PooledObject InstantiateObjectForPool(Pool pool, PooledObject prefab, Transform parent, bool startActive = false)
|
|
{
|
|
bool wasActive = prefab.gameObject.activeSelf;
|
|
if (wasActive)
|
|
{
|
|
prefab.gameObject.SetActive(false);
|
|
}
|
|
PooledObject obj = UnityEngine.Object.Instantiate(prefab, parent);
|
|
if (wasActive)
|
|
{
|
|
prefab.gameObject.SetActive(true);
|
|
}
|
|
obj.AddToPool(pool.id);
|
|
obj.name = prefab.name + "_" + pool.totalObjectsCount;
|
|
pool.totalObjectsCount++;
|
|
pool.usedObjets.Add(obj);
|
|
if (startActive)
|
|
{
|
|
obj.gameObject.SetActive(true);
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
private void GrowPool(Pool pool, PooledObject prefab, int num)
|
|
{
|
|
for (int i = 0; i < num; i++)
|
|
{
|
|
ReleaseObject(InstantiateObjectForPool(pool, prefab, poolsContainer));
|
|
}
|
|
}
|
|
|
|
private void ReleaseObject(PooledObject pooledObject)
|
|
{
|
|
if (pooledObject == null)
|
|
{
|
|
return;
|
|
}
|
|
if (!pooledObject.Used)
|
|
{
|
|
Debug.LogWarning("Releasing a non used object");
|
|
return;
|
|
}
|
|
Pool pool = GetPoolId(pooledObject.PoolId);
|
|
if (pool == null)
|
|
{
|
|
Debug.LogWarning("Releasing used object but no pool found");
|
|
return;
|
|
}
|
|
if (pool.usedObjets.Contains(pooledObject))
|
|
{
|
|
pool.usedObjets.Remove(pooledObject);
|
|
}
|
|
pool.freeObjects.Add(pooledObject);
|
|
pooledObject.Release();
|
|
pooledObject.gameObject.SetActive(false);
|
|
pooledObject.transform.SetParent(poolsContainer);
|
|
}
|
|
|
|
private void OnApplicationQuit()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
private void Clear()
|
|
{
|
|
if (pools == null)
|
|
{
|
|
return;
|
|
}
|
|
foreach (KeyValuePair<int, Pool> entry in pools)
|
|
{
|
|
foreach (PooledObject free in entry.Value.freeObjects)
|
|
{
|
|
if (free != null)
|
|
{
|
|
free.RemoveFromPool();
|
|
}
|
|
}
|
|
entry.Value.freeObjects.Clear();
|
|
foreach (PooledObject used in entry.Value.usedObjets)
|
|
{
|
|
if (used != null)
|
|
{
|
|
used.RemoveFromPool();
|
|
}
|
|
}
|
|
entry.Value.usedObjets.Clear();
|
|
}
|
|
pools.Clear();
|
|
}
|
|
|
|
public void SaveCurrentToPreloading()
|
|
{
|
|
preloadPrefabs.Clear();
|
|
foreach (KeyValuePair<int, Pool> entry in pools)
|
|
{
|
|
var preload = new PreloadPrefab();
|
|
preload.prefab = entry.Value.prefab;
|
|
preload.preloadCount = entry.Value.totalObjectsCount;
|
|
preloadPrefabs.Add(preload);
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public class PreloadPrefab
|
|
{
|
|
public PooledObject prefab;
|
|
|
|
public int preloadCount;
|
|
|
|
}
|
|
|
|
private class Pool
|
|
{
|
|
public int id = -1;
|
|
|
|
public PooledObject prefab;
|
|
|
|
public List<PooledObject> freeObjects = new List<PooledObject>();
|
|
|
|
public HashSet<PooledObject> usedObjets = new HashSet<PooledObject>();
|
|
|
|
public int totalObjectsCount;
|
|
|
|
}
|
|
|
|
}
|
|
}
|