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# 스크립트 성능 향상: [링크]
★☆☆☆☆
반응형
'개발 > Unity' 카테고리의 다른 글
Unity) Android Permission 안드로이드 권한 설정 (0) | 2021.04.07 |
---|---|
문제해결)Unity) APK 열기 비활성화 및 앱 노출 안 되는 현상 (0) | 2021.04.06 |
Unity) Shader Graph #2 캐릭터 스폰 효과 구현 (0) | 2021.04.05 |
Unity) 2D Tile Map 만들기 (0) | 2021.04.03 |
Unity) Bool 값 인스펙터에서 변경 시 이벤트 처리하기 (0) | 2021.03.24 |
댓글