Practice_Unity/Assets/Scripts/Managers/PoolManager.cs
SEAN-59 ee2026017f 작업
1. 리소스 메니저 생성
2. 풀 매니저 생성
3. 조이스틱 생성 - 조이스틱 이미지 잘 움직이는것도 확인 함

To-Do
1. 조이스틱과 플레이어 캐릭터를 연결하는 로직
2. 몬스터 이동 로직을 고민해서 구현해보기
2025-09-21 23:55:29 +09:00

177 lines
5.1 KiB
C#

using System.Collections.Generic;
using UnityEngine;
public class PoolManager : IManager
{
#region Pool
/// <summary>
/// 개별 오브젝트 풀.
/// </summary>
class Pool
{
// 이 풀이 관리하는 오브젝트의 원본 프리팹 경로
private string _path;
// 이 풀의 오브젝트들을 담아둘 부모 Transform
public Transform Root { get; private set; }
// 비활성화된 오브젝트(재고)를 담아두는 스택
private Stack<GameObject> _poolStack = new Stack<GameObject>();
/// <summary>
/// 풀 초기화
/// </summary>
public void Init(string path, int count)
{
_path = path;
GameObject original = Manager.Resource.Load<GameObject>(_path);
if(original == null)
{
Debug.LogError($"Pool Init Failed! Original prefab not found at path: {_path}");
return;
}
Root = new GameObject() { name = $"{original.name}_Root" }.transform;
for (int i = 0; i < count; i++)
{
Push(Create(original));
}
}
/// <summary>
/// 새 오브젝트 생성. Poolable 컴포넌트를 추가하고 경로를 지정.
/// </summary>
private GameObject Create(GameObject original)
{
GameObject go = Object.Instantiate(original);
go.name = original.name;
go.AddComponent<Poolable>().Path = _path;
return go;
}
/// <summary>
/// 다 쓴 오브젝트를 풀에 반납 (비활성화 후 스택에 추가)
/// </summary>
public void Push(GameObject go)
{
if (go == null) return;
go.transform.SetParent(Root);
go.SetActive(false);
_poolStack.Push(go);
}
/// <summary>
/// 풀에서 오브젝트를 꺼냄 (재고가 있으면 재고 사용, 없으면 새로 생성)
/// </summary>
public GameObject Pop(Transform parent)
{
GameObject go;
if (_poolStack.Count > 0)
{
go = _poolStack.Pop();
}
else
{
// 풀이 비었을 경우, 새로 5개를 생성하여 풀에 추가합니다.
GameObject original = Manager.Resource.Load<GameObject>(_path);
for (int i = 0; i < 5; i++)
{
Push(Create(original));
}
// 이제 풀이 채워졌으니, 하나를 꺼내서 사용합니다.
go = _poolStack.Pop();
}
go.SetActive(true);
// @DontDestroyOnLoad 해제 부
// if(parent == null)
// poolable.transform.parent = Managers.Scene.CurrentScene.transform;
go.transform.SetParent(parent);
return go;
}
}
#endregion
// 모든 풀들을 관리하는 딕셔너리. <프리팹 경로, 풀>
private Dictionary<string, Pool> _pools = new Dictionary<string, Pool>();
private Transform _root;
/// <summary>
/// PoolManager 초기화. @Pool_Root 오브젝트 생성.
/// </summary>
public void Init()
{
if (_root == null)
{
_root = new GameObject { name = "@Pool_Root" }.transform;
Object.DontDestroyOnLoad(_root);
}
}
/// <summary>
/// 게임 시작 시 미리 풀을 생성해 둠.
/// </summary>
public void CreatePool(string path, int count = 5)
{
if (_pools.ContainsKey(path))
{
Debug.LogWarning($"Pool already exists for path: {path}");
return;
}
Pool pool = new Pool();
pool.Init(path, count);
pool.Root.SetParent(_root);
_pools.Add(path, pool);
}
/// <summary>
/// 풀에서 오브젝트를 꺼내 사용.
/// </summary>
public GameObject Pop(string path, Transform parent = null)
{
// 요청한 풀이 없으면 새로 1개짜리 풀을 생성
if (!_pools.ContainsKey(path))
{
CreatePool(path, 1);
}
return _pools[path].Pop(parent);
}
/// <summary>
/// 사용이 끝난 오브젝트를 풀에 반납.
/// </summary>
public void Push(GameObject go)
{
// 오브젝트의 Poolable 컴포넌트에서 원본 경로를 찾아냄
string path = go.GetComponent<Poolable>()?.Path;
if (string.IsNullOrEmpty(path) || !_pools.ContainsKey(path))
{
Debug.LogWarning("Push failed! Check if object is poolable or if pool exists.");
Object.Destroy(go);
return;
}
// 경로에 맞는 풀에 오브젝트를 반납
_pools[path].Push(go);
}
/// <summary>
/// 모든 풀의 오브젝트들을 파괴하고 풀 목록을 초기화.
/// </summary>
public void Clear()
{
foreach (Transform child in _root)
{
GameObject.Destroy(child.gameObject);
}
_pools.Clear();
}
}