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;
|
|
|
|
//음... 클래스 타입별로 풀을 만드는건?
|
|
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
|
|
//현재 Resources.Load 기반으로 구현...
|
|
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
|
|
|
|
//리소스 관리로 이전 예정
|
|
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은 custom shader를 포함하지 않으므로 불러올 시점에 shader를 재설정해준다.
|
|
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
|
|
}
|
|
} |