191 lines
5.8 KiB
C#
191 lines
5.8 KiB
C#
|
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
|
|||
|
}
|
|||
|
}
|