Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

1vdlrwnsv1 님의 블로그

unity 오브젝트 풀링 매니저 본문

Unity 최종

unity 오브젝트 풀링 매니저

1vdlrwnsv1 2025. 4. 25. 21:02

사용 기술

  • 싱글톤 패턴: 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)

역할

  • 객체를 풀에서 꺼내서 위치/회전/부모 설정 후 활성화함.

내부 동작 순서

  1. resource.ResourceInstanceID로 풀에서 검색.
  2. 있으면 꺼내고(queue.Dequeue()), 없으면 Instantiate().
  3. 부모, 위치, 회전 설정.
  4. SetActive(true)로 활성화.
  5. 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)

 

역할

  • 오브젝트를 풀에 다시 집어넣고 비활성화

 내부 동작

  1. IPoolable 컴포넌트 확인
  2. 없으면 경고 로그
  3. Dictionary에 해당 키의 큐 없으면 새로 생성
  4. SetActive(false)로 비활성화
  5. 부모를 ObjectPoolManager로 설정
  6. 큐에 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();
}