Instantiate, Destroy를 사용할수록 파편화된 메모리가 누적된다. 따라서 Instantiate, Destroy를 최소한으로 사용하기 위해 오브젝트를 새로 복제, 파괴하기 전에 오브젝트를 오브젝트 풀 안에서 유지관리하면서 사전에 사용했던 오브젝트를 풀로부터 다시 가져와서 활용하는 방식을 오브젝트 풀링이라고 한다.
게임 매니저에 Dongle과 ParticleSystem 오브젝트가 저장될 리스트들을 선언해서 풀을 만들어준다.
오브젝트풀 관리를 위한 사이즈, 커서 변수또한 추가해준다.
public GameObject donglePrefab; //동글 프리팹
public Transform dongleGroup; //동글이 생성될 위치
public List<Dongle> donglePool;
public GameObject effectPrefab; //이펙트 프리팹
public Transform effectGroup; //이펙트가 생성될 위치
public List<ParticleSystem> effectPool;
[Range(1, 30)]
public int poolSize;
public int poolCursor;
[Range(N, M)] : 인스펙터 창에서 슬라이더 형식으로 N부터 M까지의 값을 조절할 수 있다.
오브젝트 풀을 만들기 위한 함수를 생성한다.
private void Awake()
{
Application.targetFrameRate = 60;
donglePool = new List<Dongle>();
effectPool = new List<ParticleSystem>();
for (int i = 0; i < poolSize; i++)
{
MakeDongle(); //풀 만들기
}
}
Dongle MakeDongle()
{
//이펙트 생성
GameObject instantEffectObj = Instantiate(effectPrefab, effectGroup);
instantEffectObj.name = "Effect " + effectPool.Count; //이름을 설정
ParticleSystem instantEffect = instantEffectObj.GetComponent<ParticleSystem>();
effectPool.Add(instantEffect);
//동글 프리팹 복사해서 가져옴, 이 때 부모는 동글 그룹으로 설정
GameObject instantDongleObj = Instantiate(donglePrefab, dongleGroup);
instantDongleObj.name = "Dongle " + donglePool.Count; //이름을 설정
Dongle instantDongle = instantDongleObj.GetComponent<Dongle>();
instantDongle.manager = this; //manager 변수도 초기화
instantDongle.effect = instantEffect;
donglePool.Add(instantDongle);
return instantDongle;
}
poolSize를 10으로 설정하고 Run하면 아래 사진과 같이 Dongle, Effect가 각각 10개씩 만들어진 것을 확인할 수 있다.
이제 생성된 동글을 사용하도록 GetDongle을 수정한다.
Dongle GetDongle()
{
for(int i=0;i<donglePool.Count;i++)
{
poolCursor = (poolCursor+1) % donglePool.Count; //커서가 오브젝트 풀을 계속 회전하도록 설정
if(!donglePool[poolCursor].gameObject.activeSelf) //비활성화된 오브젝트를 찾으면 해당 오브젝트를 사용
{
return donglePool[poolCursor]; //비활성화 되어있는 동글을 넘김
}
}
return MakeDongle(); //만약 donglePool에 없다면 MakeDongle로 풀에 하나 추가해서 넘김
}
이 때 Run을 해보면 재사용되는 동글이 기존에 비활성화됐던 위치 그대로 나타나는 것을 확인할 수 있다. 이를 재사용 로직을 구현해서 보완한다.
동글이 합쳐지면서 비활성화 될 때 모든 정보를 초기화해주기 위해 OnDisable 함수를 이용해 로직을 구현한다.
void OnDisable()
{
//동글 속성 초기화
level = 0;
isDrag = false;
isMerge = false;
isAttach = false;
//동글 트랜스폼 초기화
transform.localPosition = Vector3.zero;
transform.localRotation = Quaternion.identity;
transform.localScale = Vector3.zero;
//동글 물리 초기화
rigid.simulated = false;
rigid.velocity = Vector2.zero;
rigid.angularVelocity = 0;
circle.enabled = true;
}
하이어라키 창의 오브젝트들의 활성화/비활성화를 보면 오브젝트 풀링이 정상 작동하고 있다는 것을 알 수 있다.