1vdlrwnsv1 님의 블로그
unity 오브젝트 풀링 매니저 본문
사용 기술
- 싱글톤 패턴: ObjectPoolManager.Instance로 어디서든 접근 가능.
주요 필드
private readonly Dictionary<int, Queue<GameObject>> pools = new();
설명
- Dictionary<int, Queue<GameObject>>
- key: IPoolable.ResourceInstanceID (오브젝트를 식별할 유니크 ID)
- value: 재사용 가능한 오브젝트들을 담은 Queue<GameObject>
사용 기술
- 자료구조: Dictionary + Queue 조합
public GameObject GetObjectInPool(IPoolable resource, Vector3 position, Quaternion rotation, Transform parent = null)
public GameObject GetObjectInPool(IPoolable resource, Vector3 position, Quaternion rotation, Transform parent = null)
역할
- 객체를 풀에서 꺼내서 위치/회전/부모 설정 후 활성화함.
내부 동작 순서
- resource.ResourceInstanceID로 풀에서 검색.
- 있으면 꺼내고(queue.Dequeue()), 없으면 Instantiate().
- 부모, 위치, 회전 설정.
- SetActive(true)로 활성화.
- IPoolable.IsAutoReturn이 true면 자동 반환 코루틴 등록.
사용 기술
- Transform.SetPositionAndRotation: Unity 2021+부터 지원되는 편리 API.
- StartCoroutine: Unity 코루틴으로 비동기 처리.
- 인터페이스 프로그래밍: IPoolable을 통해 객체 제어.
AutoReturn 코루틴
private IEnumerator AutoReturn(GameObject obj, float delay)
역할
- 일정 시간(delay) 후 오브젝트 자동 반환
사용 기술
- yield return new WaitForSeconds(delay): 딜레이를 주는 코루틴 문법.
ReturnObjectToPool
public void ReturnObjectToPool(GameObject instance)
역할
- 오브젝트를 풀에 다시 집어넣고 비활성화
내부 동작
- IPoolable 컴포넌트 확인
- 없으면 경고 로그
- Dictionary에 해당 키의 큐 없으면 새로 생성
- SetActive(false)로 비활성화
- 부모를 ObjectPoolManager로 설정
- 큐에 enqueue
AutoReturnToPool
public void AutoReturnToPool(GameObject obj, float delay)
역할
- 외부에서 자동 반환 요청할 때 코루틴 실행
ObjectPoolManager.cs
using System.Collections.Generic;
using System.Collections;
using DataDeclaration;
using UnityEngine;
/// <summary>
/// 사용법
/// 1. `GetObjectInPool`로 풀에서 오브젝트 꺼내옴
/// - `IPoolable` 인터페이스 있는 애들만 관리됨
/// - 위치 회전 부모 설정 가능
/// 2. `ReturnObjectToPool`로 객체 풀에 반환함
/// - 반환된 객체는 비활성화되고 나중에 재사용됨
/// 3. `AutoReturnToPool`은 일정 시간 후 자동으로 객체 반환해줌
/// - 정해진 시간 지나면 자동 반환됨
///
/// 예시
/// 1. 객체 꺼내는 법
/// GameObject pooledObject = ObjectPoolManager.Instance.GetObjectInPool(resource position rotation);
///
/// 2. 객체 반환하는 법
/// ObjectPoolManager.Instance.ReturnObjectToPool(pooledObject);
/// ObjectPoolManager.Instance.AutoReturnToPool(pooledObject, impactPoolable.ReturnTime);
/// </summary>
public sealed class ObjectPoolManager : SingletonBehaviour<ObjectPoolManager>
{
private readonly Dictionary<int, Queue<GameObject>> pools = new();
public GameObject GetObjectInPool(IPoolable resource, Vector3 position, Quaternion rotation, Transform parent = null)
{
GameObject instance;
var key = resource.ResourceInstanceID;
if (pools.TryGetValue(key, out var queue) && queue.Count > 0)
{
instance = queue.Dequeue();
}
else
{
instance = Instantiate(resource.GameObject);
}
instance.transform.SetParent(parent ? parent : null);
instance.transform.SetPositionAndRotation(position, rotation);
instance.SetActive(true);
// 인스턴스에서 Poolable 컴포넌트 꺼내서 적용
var poolable = instance.GetComponent<IPoolable>();
if (poolable != null && poolable.IsAutoReturn)
{
StartCoroutine(AutoReturn(instance, poolable.ReturnTime));
}
return instance;
}
private IEnumerator AutoReturn(GameObject obj, float delay)
{
yield return new WaitForSeconds(delay);
if (obj != null && obj.activeInHierarchy)
{
ReturnObjectToPool(obj);
}
}
public void ReturnObjectToPool(GameObject instance)
{
var poolable = instance.GetComponent<IPoolable>();
if (poolable == null)
{
Debug.LogWarning($"[ObjectPoolManager] 반환 실패: IPoolable이 없음");
return;
}
int key = poolable.ResourceInstanceID;
if (!pools.TryGetValue(key, out var queue))
{
queue = new Queue<GameObject>();
pools[key] = queue;
}
instance.SetActive(false);
instance.transform.SetParent(transform);
queue.Enqueue(instance);
}
public void AutoReturnToPool(GameObject obj, float delay)
{
StartCoroutine(AutoReturn(obj, delay));
}
}
PoolableResource.cs
public class PoolableResource : MonoBehaviour, IPoolable
설명
- 실제로 풀링 대상이 되는 게임 오브젝트에 붙는 컴포넌트
- IPoolable 인터페이스 구현체
프로퍼티 설명
[field: SerializeField] public bool IsAutoReturn { get; private set; } = true;
[field: SerializeField] public float ReturnTime { get; private set; } = 5f;
- 자동 프로퍼티의 백킹 필드에 직렬화 적용
- Unity 인스펙터에서 설정 가능
나머지
public GameObject GameObject => gameObject;
public int ResourceInstanceID => gameObject.GetInstanceID();
오브젝트 참조와 유니크 ID 제공
기술 요약
기술/패턴설명
Singleton | 어디서든 접근 가능, 전역 객체 |
Object Pooling | 오브젝트 재사용으로 성능 최적화 |
Coroutine | 일정 시간 후 자동 반환 처리 |
Interface | IPoolable로 유연한 설계 |
Dictionary+Queue | 빠른 조회와 순차 처리 |
Modern C# 문법 | [field: SerializeField], ??, =>, var, new() 등 사용 |
PoolableResource.cs
using DataDeclaration;
using UnityEngine;
public class PoolableResource : MonoBehaviour, IPoolable
{
[field: SerializeField] public bool IsAutoReturn { get; private set; } = true;
[field: SerializeField] public float ReturnTime { get; private set; } = 5f;
public GameObject GameObject => gameObject;
public int ResourceInstanceID => gameObject.GetInstanceID();
}
'Unity 최종' 카테고리의 다른 글
Unity3D 적 탐지 시스템 구현 (0) | 2025.04.30 |
---|---|
Unity 클래스 구조 변경 (0) | 2025.04.28 |
유니티 PlayerPref를 이용한 사운드 값, 마우스 감도 값 저장 불러오기 (0) | 2025.04.23 |
옵션을 만들자 (0) | 2025.04.22 |
무기 교체, 아이템 장착 시스템 구현 (0) | 2025.04.17 |