2022. 9. 13. 18:02ㆍ유니티 unity
참고 영상
https://www.youtube.com/watch?v=JxP-kqstMAY
오브젝트 풀링은
자주 사용되는 미사일이나 이펙트 등 계속해서 생성되고 파괴되는 오브젝트의 최적화를 위해서 사용됩니다.
비용이 큰 생성과 파괴를 계속해서 사용하는 대신 활성화시키고 비활성화시키는 방법입니다.
생성과 파괴가 반복적으로 일어나면 가비지 컬렉터가 발생하는데 이 때 렉을 발생할 수도 있습니다.
자주 사용되는 오브젝트는 오브젝트풀링으로 관리하면 프레임 저하를 막을 수 있습니다.
보통 따로 큐 나 스택으로 직접 오브젝트풀링을 만들어야 하지만
유니티 2021.3버전부터는 정식으로 오브젝트 풀링 기능을 지원합니다.
https://docs.unity3d.com/ScriptReference/Pool.ObjectPool_1.html
여러 가지 컬렉션을 사용할 수 있는데
스택이 가장 빠르다는 문서가 있어서 스택을 사용하는 ObjectPool를 사용하겠습니다.
쉽게 생각하시면 생성할 때 Get
파괴할 때 Release를 사용한다고 생각하시면 됩니다.
https://docs.unity3d.com/ScriptReference/Pool.ObjectPool_1-ctor.html
public ObjectPool<T0>(Func<T> createFunc, Action<T> actionOnGet, Action<T> actionOnRelease, Action<T> actionOnDestroy, bool collectionCheck, int defaultCapacity, int maxSize);
사용법을 간단하게 설명하자면
createFunc = 풀이 비어 있을 때 새로운 인스턴스를 만드는 데 사용
actionOnGet = 풀에서 인스턴스를 가져올 때 호출
actionOnRelease = 인스턴스가 풀로 반환될 때 호출
actionOnDestroy = 인스턴스가 파괴될 때 호출
collectionCheck = 컬렉션 검사가 수행합니다. 인스턴스가 이미 풀에 있는 경우 예외가 발생합니다.
defaultCapacity = 스택의 기본 크기
maxSize = 풀의 최대 크기
CountActive | 풀에서 사용 중인 개체 수 |
CountAll | 풀의 개체 수 |
CountInactive | 풀에서 사용하지 않는 개체 수 |
Clear | 해당 풀의 모든 항목을 제거합니다.파괴 콜백(actionOnDestroy)이 호출됩니다 |
Dispose | 해당 풀의 모든 항목을 제거합니다.파괴 콜백(actionOnDestroy)이 호출됩니다 |
public ObjectPool(
Func<T> createFunc,
Action<T> actionOnGet = null,
Action<T> actionOnRelease = null,
Action<T> actionOnDestroy = null,
bool collectionCheck = true,
int defaultCapacity = 10,
int maxSize = 10000)
{
if (createFunc == null)
throw new ArgumentNullException(nameof (createFunc));
if (maxSize <= 0)
throw new ArgumentException("Max Size must be greater than 0", nameof (maxSize));
this.m_Stack = new Stack<T>(defaultCapacity);
this.m_CreateFunc = createFunc;
this.m_MaxSize = maxSize;
this.m_ActionOnGet = actionOnGet;
this.m_ActionOnRelease = actionOnRelease;
this.m_ActionOnDestroy = actionOnDestroy;
this.m_CollectionCheck = collectionCheck;
}
기본 예제
스페이스 사용 시 큐브 생성
using UnityEngine;
using UnityEngine.Pool;
public class Cube : MonoBehaviour
{
public IObjectPool<Cube> pool;
private void OnEnable()
{
Invoke(nameof(Dead),Random.Range(0.5f, 1.5f));
}
private void Dead()
{
pool.Release(this);
}
}
프리팹에 들어가 있는 스크립트
using UnityEngine;
using UnityEngine.Pool;
public class PoolExample : MonoBehaviour
{
IObjectPool<Cube> _Pool;
public GameObject cubePrefab;
public bool collectionChecks = true;
public int maxPoolSize = 30;
public IObjectPool<Cube> Pool
{
get
{
if (_Pool == null)
{
_Pool = new ObjectPool<Cube>(CreatePooledItem, OnTakeFromPool, OnReturnedToPool, OnDestroyPoolObject,collectionChecks,defaultCapacity:10,maxSize:maxPoolSize);
}
return _Pool;
}
}
//생성시 호출되는 함수(풀에없을때 생성됩니다)
Cube CreatePooledItem()
{
//생성시키고 스크립트 Cube를 가져옵니다.
var cube = Instantiate(cubePrefab).GetComponent<Cube>();
//pool 설정
cube.pool = Pool;
return cube;
}
// Release 사용시 호출되는 함수
void OnReturnedToPool(Cube cube)
{
cube.gameObject.SetActive(false);
}
// Get 사용시 호출되는 함수
void OnTakeFromPool(Cube cube)
{
cube.gameObject.SetActive(true);
}
// 만약 정해진 풀 용량에 도달하면 반환된 모든 항목이 삭제됩니다.
// 삭제시 호출되는 함수
void OnDestroyPoolObject(Cube cube)
{
Destroy(cube.gameObject);
}
private void Update()
{
//스페이스 누를 때 랜덤하게 큐브 생성하는 함수입니다.
if (Input.GetKey(KeyCode.Space))
{
Vector3 ran = new Vector3(Random.Range(-20f, 20f), 0, Random.Range(-20f, 20f));
var cube = Pool.Get();
cube.transform.position = ran;
}
}
}
최대 풀의 크기가 30개라서 30개가 초과하면 삭제됩니다. 이때 파괴가 발생이 되어 가비지 컬렉션이 발생될 수도 있으니 풀의 최대 크기는 크게 설정해야 합니다.
평소에는 큐로 오브젝트 풀링 기능을 구현해서 써봤는데 유니티에서 정식으로 지원한다고 하니 이제부터 이걸 써야겠네요
'유니티 unity' 카테고리의 다른 글
unity // 구글플레이 인앱업데이트 안드로이드14 타켓 오류 (1) | 2024.06.09 |
---|---|
[유니티] 문자열을 이용하여 클래스 인스턴스 생성하기 :상속 관계에서의 동적 클래스 생성 (0) | 2024.03.24 |
유니티(Unity) Job 시스템 사용법-1 (0) | 2022.08.23 |
Unity / 베지어곡선이용해서 라인렌더로 곡선 그리기 (0) | 2022.08.16 |
유니티(Unity) Quaternion 전부 알기 (0) | 2022.08.15 |