AssetBase/Assets/FirstVillain/ObjectPool/PoolManager.cs

191 lines
5.8 KiB
C#
Raw Permalink Normal View History

using FirstVillain.Singleton;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Pool;
namespace FirstVillain.ObjectPool
{
//GameObject Pooling
public class PoolManager : UnitySingleton<PoolManager>
{
[SerializeField] private int _capacity = 10;
[SerializeField] private int _maxSize = 1000;
[SerializeField] private bool _collectionCheck = true;
//<2F><>... Ŭ<><C5AC><EFBFBD><EFBFBD> Ÿ<>Ժ<EFBFBD><D4BA><EFBFBD> Ǯ<><C7AE> <20><><EFBFBD><EFBFBD><EFBFBD>°<EFBFBD>?
private Dictionary<string, PoolItem> _poolDict = new();
public GameObject Spawn(string path, Transform parent = null)
{
string name = Path.GetFileName(path);
if(!_poolDict.ContainsKey(name))
{
CreatePoolItem(path);
}
var pooledObj = _poolDict[name].Pool.Get();
if (parent != null)
{
pooledObj.transform.Reset(parent);
}
return pooledObj;
}
public T Spawn<T>(string path, Transform parent = null)
{
return Spawn(path, parent).GetComponent<T>();
}
public void ReleaseGameObject(GameObject obj)
{
if (_poolDict.ContainsKey(obj.name))
{
try
{
obj.transform.Reset();
try
{
_poolDict[obj.name].Pool.Release(obj);
}
catch
{
obj.SetActive(false);
}
}
catch (Exception ex)
{
Debug.LogError($"Exception has occured!!! Object : {obj.name} === {ex.Message}");
}
}
else
{
Debug.LogWarning($"Object[{obj.name}] does not exist in pool dictionary. But it's been destroyed anyway :D");
Destroy(obj);
}
}
#region Create Pool
//<2F><><EFBFBD><EFBFBD> Resources.Load <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>...
public void CreatePoolItem(string path)
{
string resourceName = Path.GetFileName(path);
if(!_poolDict.ContainsKey(resourceName))
{
var resource = LoadAssetOnResources<GameObject>(path);
var pool = new PoolItem(path, CreateNewObjectPool(resource, resourceName));
_poolDict.Add(resourceName, pool);
}
}
private ObjectPool<GameObject> CreateNewObjectPool(GameObject prefab, string resourceName)
{
return new ObjectPool<GameObject>(
() =>
{
GameObject obj = Instantiate(prefab);
obj.name = resourceName;
return obj;
},
OnGetItem,
OnReleaseItem,
OnDestroyItem,
_collectionCheck /* Collection checks will throw errors if we try to release an item that is already in the pool.*/,
_capacity/*defalut capacity*/,
_maxSize
);
}
private void OnGetItem(GameObject obj)
{
obj.SetActive(true);
}
private void OnReleaseItem(GameObject obj)
{
obj.SetActive(false);
}
private void OnDestroyItem(GameObject obj)
{
Destroy(obj);
}
#endregion Create Pool
#region Resource Load
//<2F><><EFBFBD>ҽ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
public T LoadAssetOnResources<T>(string resourcePath) where T : UnityEngine.Object
{
var resourceObj = Resources.Load<T>(resourcePath);
if (resourceObj == null)
{
throw new ResourceCriticalException($"Cannot Load Resources Object [{resourcePath}]");
}
return resourceObj;
}
#endregion Resource Load
#region AssetBundle Refresh Shader
private void RefreshShader<T>(UnityEngine.Object obj)
{
//AssetBundle<6C><65> custom shader<65><72> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD> <20>ҷ<EFBFBD><D2B7><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> shader<65><72> <20><EFBFBD><E7BCB3><EFBFBD><EFBFBD><EFBFBD>ش<EFBFBD>.
if (typeof(GameObject) == typeof(T))
{
GameObject go = obj as GameObject;
if (go.GetComponents<Renderer>() != null)
{
RefreshShader(go.GetComponents<Renderer>());
}
if (go.GetComponentsInChildren<Renderer>(true) != null)
{
RefreshShader(go.GetComponentsInChildren<Renderer>(true));
}
}
else if (typeof(Material) == typeof(T))
{
RefreshShader(obj as Material);
}
}
private void RefreshShader(Material material)
{
Shader shader = Shader.Find(material.shader.name);
if (shader != null)
{
material.shader = shader;
}
else
{
Debug.LogWarning(string.Format("unable to refresh shader: [{0}] in material [{1}]", material.shader.name, material.name));
}
}
private void RefreshShader(Renderer[] renderers)
{
if (null == renderers)
{
return;
}
for (int i = 0; i < renderers.Length; i++)
{
Material[] materials = renderers[i].sharedMaterials;
for (int j = 0; j < materials.Length; j++)
{
if (materials[j] == null) { continue; }
RefreshShader(materials[j]);
}
}
}
#endregion AssetBundle Refresh Shader
}
}