Unity_Learn/Assets/Scripts/Managers/PoolManager.cs
2025-09-10 12:54:42 +09:00

132 lines
3.8 KiB
C#

using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class PoolManager
{
#region Pool
// Pool하는데 만약에 A 와 B가 있는데 이게 전부 다 같은 Pool_root 밑에 있으면
// A를 Push 했다가 B를 Pop 할 수도 있음
// 그래서 A와 B를 구분하기 위해서 Dictionary를 사용함
class Pool
{
public GameObject Original {get; private set;}
// A 나 B같은 오브젝트들이 뭉쳐질 위치
public Transform Root {get; private set;}
// 스택 큐 다상관 없는데
Stack<Poolable> _poolStack = new Stack<Poolable>();
public void Init(GameObject original, int count = 5)
{
Original = original;
Root = new GameObject().transform;
Root.name = $"{original.name}_Root";
for (int i = 0; i < count; i++)
{
Poolable poolable = Create();
Push(poolable);
}
}
Poolable Create()
{
GameObject go = Object.Instantiate<GameObject>(Original);
go.name = Original.name;
return go.GetOrAddComponent<Poolable>();
}
public void Push(Poolable poolable)
{
if(poolable == null) return;
poolable.transform.parent = Root;
poolable.gameObject.SetActive(false);
poolable.IsUsing = false;
_poolStack.Push(poolable);
}
public Poolable Pop(Transform parent)
{
Poolable poolable;
if(_poolStack.Count > 0)
poolable = _poolStack.Pop();
else
poolable = Create();
poolable.gameObject.SetActive(true);
//@DontDestroyOnLoad 해제
if (parent == null)
poolable.transform.parent = Managers.Scene.CurrentScene.transform;
poolable.transform.parent = parent;
poolable.IsUsing = true;
return poolable;
}
}
#endregion
Dictionary<string, Pool> _pool = new Dictionary<string, Pool>();
Transform _root;
public void Init()
{
if (_root == null)
{
_root = new GameObject { name = "@Pool_Root" }.transform;
Object.DontDestroyOnLoad(_root);
}
}
public void Push(Poolable poolable)
{
string name = poolable.gameObject.name;
if (_pool.ContainsKey(name) == false)
{
GameObject.Destroy(poolable.gameObject);
return;
}
_pool[name].Push(poolable);
}
public void CreatePool(GameObject original, int count = 5)
{
Pool pool = new Pool();
pool.Init(original, count);
pool.Root.parent = _root.transform;
_pool.Add(original.name, pool);
}
public Poolable Pop(GameObject original, Transform parent = null)
{
if(_pool.ContainsKey(original.name) == false)
CreatePool(original);
return _pool[original.name].Pop(parent);
}
public GameObject GetOriginal(string name)
{
if(_pool.ContainsKey(name) == false)
return null;
return _pool[name].Original;
// return Managers.Resource.Load<GameObject>($"Prefabs/{path}");
}
// 이걸 다 날려야 하나 안날려야 하나는 게임마다 다를거 같다.
// 대부분의 경우에는 안날려도 큰 문제는 없을거 같긴한데
// 대규모 MMORPG 같은 경우 - 지역풀이 너무 다른 경우 기존의 리소스를 날려버리고 다시 받는 경우가 있을 수 있다.
public void Clear()
{
foreach (Transform child in _root)
GameObject.Destroy(child.gameObject);
_pool.Clear();
}
}