본문 바로가기
개발/Unity

Unity) Object Pool <T>Pattern

by 테샤르 2021. 4. 5.

Object Pool Pattern

Unity Docs에서 지원하고 있는 Object Pool Pettern을 찾게 되어서 간략하게 포스팅 한다.

namespace DesignPattern.Objectpool 
{
    // The PooledObject class is the type that is expensive or slow to instantiate,
    // or that has limited availability, so is to be held in the object pool.
    public class PooledObject
    {
        private DateTime _createdAt = DateTime.Now;
 
        public DateTime CreatedAt
        {
            get { return _createdAt; }
        }
 
        public string TempData { get; set; }
    }

    // The Pool class controls access to the pooled objects. It maintains a list of available objects and a 
    // collection of objects that have been obtained from the pool and are in use. The pool ensures that released objects 
    // are returned to a suitable state, ready for reuse. 
    public static class Pool
    {
        private static List<PooledObject> _available = new List<PooledObject>();
        private static List<PooledObject> _inUse = new List<PooledObject>();
 
        public static PooledObject GetObject()
        {
            lock(_available)
            {
                if (_available.Count != 0)
                {
                    PooledObject po = _available[0];
                    _inUse.Add(po);
                    _available.RemoveAt(0);
                    return po;
                }
                else
                {
                    PooledObject po = new PooledObject();
                    _inUse.Add(po);
                    return po;
                }
            }
        }
 
        public static void ReleaseObject(PooledObject po)
        {
            CleanUp(po);
 
            lock (_available)
            {
                _available.Add(po);
                _inUse.Remove(po);
            }
        }
 
        private static void CleanUp(PooledObject po)
        {
            po.TempData = null;
        }
    }
}

실제 내가 구현해서 사용한 로직과 거의 비슷해서 놀랬다. (원리가 비슷하니 거의 비슷해야 정상이긴하다;;;)

 

Pool 오브젝트의 Count , PreLoad , CleanUpAll 같은 Method가 없는 것을 제외하고 거의 비슷하다.

Object Pooling의 핵심은 GetObject를 통해서 접근하고 내부에서는 재사용이 가능한 오브젝트가 있으면 해당 Object를 리턴 그게 아니면 새로운 오브젝트를 생성해서 리턴 , 사용이 끝난 오브젝트는 다시 Pool에 되돌려준다.



<수정된 : Unity Object Pooling >

최초 포스팅을 했던 시기보다 더 지나서 수정된 오브젝트 풀링이 있어서 추가로 포스팅한다.

 

ReviseGun Class에 Object Pool 을 선언하고 관련된 콜백과 값을 입력한다.

using UnityEngine.Pool;

public class RevisedGun : MonoBehaviour
{
    …

    // stack-based ObjectPool available with Unity 2021 and above
    private IObjectPool<RevisedProjectile> objectPool;

    // throw an exception if we try to return an existing item, already in the pool
    [SerializeField] private bool collectionCheck = true;

    // extra options to control the pool capacity and maximum size
    [SerializeField] private int defaultCapacity = 20;
    [SerializeField] private int maxSize = 100;

    private void Awake()
    {
        objectPool = new ObjectPool<RevisedProjectile>(CreateProjectile,
            OnGetFromPool, OnReleaseToPool, OnDestroyPooledObject,
            collectionCheck, defaultCapacity, maxSize);
    }

    // invoked when creating an item to populate the object pool
    private RevisedProjectile CreateProjectile()
    {
        RevisedProjectile projectileInstance = Instantiate(projectilePrefab);
        projectileInstance.ObjectPool = objectPool;
        return projectileInstance;
    }

    // invoked when returning an item to the object pool
    private void OnReleaseToPool(RevisedProjectile pooledObject)
    {
        pooledObject.gameObject.SetActive(false);
    }

    // invoked when retrieving the next item from the object pool
    private void OnGetFromPool(RevisedProjectile pooledObject)
    {
        pooledObject.gameObject.SetActive(true);
    }

    // invoked when we exceed the maximum number of pooled items (i.e. destroy the pooled object)
    private void OnDestroyPooledObject(RevisedProjectile pooledObject)
    {
        Destroy(pooledObject.gameObject);
    }

    private void FixedUpdate()
    {
        …

    }
}


해당 오브젝트 풀에서 가져오려면 Get을 사용해서 가져온다.

RevisedProjectile bulletObject = objectPool.Get();

사용하고 난 뒤에는 재사용하기 위해서 Release를 해야한다.

objectPool.Release(bulletObject);

 


장점으로는 특정 사용 사례가없는 경우에 새로 생성하는 프로세스부터 진행하지 않고 미리 만들어진 오브젝트를 재사용하는 것으로 효율적으로 사용이 가능하다.

 

 

개체 풀링을 사용하여 C# 스크립트 성능 향상: [링크]

 

Use object pooling to boost performance of C# scripts in Unity

Learn how to build and maintain an organized and readable codebase with object pooling, and how it can help improve your game’s performance.

unity.com

 

★☆

 

반응형

댓글