유니티 2D 아이템 드랍 오브젝트 폴링으로 구현하기
오브젝트 폴링
몬스터가 아이템 드롭을 하는걸 계속 Instantiate로 생성을 하고 플레이어가 먹으면 Destroy를 하는데 이게 너무 지속되면 GC가 호출될 때 프레임이 튀는 경우가 있어 이걸 방지하기 위해 미리 오브젝트를 만들고 위치 변경만 해서 마치 '생성하는 것처럼 보이게'하는 메모리 관리 기법입니다.
운영체제 강의들을 봤을 때 메모리 단편화에 대한 관리도 골치아프니 오브젝트 폴링을 해서 메모리 관리를 하는게 공간적으로나 시간적으로나 큰 이득을 볼 수 있습니다. 그래서 이번에 리스트를 이용해 간단한 오브젝트 폴링을 만들어 봤습니다.
소스코드
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ItemDropManager : MonoBehaviour{
public static ItemDropManager Instance;
[SerializeField]
private GameObject itemPrefab;
//private Queue<PickUpItem> dropItemPool = new Queue<PickUpItem>();
private List<PickUpItem> itemPool = new List<PickUpItem>();
int rand;
private void Awake(){
Instance = this;
Init(5);
}
private PickUpItem Create(){
var obj = Instantiate(itemPrefab).GetComponent<PickUpItem>();
obj.gameObject.SetActive(false);
obj.transform.SetParent(transform);
return obj;
}
private void Init(int count){
for(int i = 0; i < count; i++){
itemPool.Add(Create());
}
}
public static PickUpItem GetItem(){
int rand = Random.Range(0, Instance.itemPool.Count);
var obj = Instance.itemPool[rand];
Instance.itemPool.RemoveAt(rand);
obj.transform.SetParent(null);
obj.gameObject.SetActive(true);
return obj;
}
public static void ReturnItem(PickUpItem item){
item.gameObject.SetActive(false);
item.transform.SetParent(Instance.transform);
Instance.itemPool.Add(item);
}
}
유튜브에 있는 폴링은 대부분 슈팅 게임을 가정하고 큐를 사용하는데 큐를 사용하게 되면 아이템들이 정해진 순서대로 나가 랜덤성이 떨어진다고 생각하고 리스트와 랜덤을 이용해서 제작을 했습니다.
public static PickUpItem GetItem(){
int rand = Random.Range(0, Instance.itemPool.Count);
var obj = Instance.itemPool[rand];
Instance.itemPool.RemoveAt(rand);
obj.transform.SetParent(null);
obj.gameObject.SetActive(true);
return obj;
}
public static void ReturnItem(PickUpItem item){
item.gameObject.SetActive(false);
item.transform.SetParent(Instance.transform);
Instance.itemPool.Add(item);
}
사실상 여기서 핵심인 내용인데 Random.Range를 통해서 리스트의 랜덤한 인덱스에서 아이템을 가져오고 RemoveAt을 통해서 중복없이 아이템을 가져갈 수 있게 했습니다. 따지자면 아이작의 아이템들과 비슷한 느낌입니다.
또한 플레이어가 필드에서 아이템을 먹으면 Ui로만 표시되고 필드의 아이템은 사라져야 합니다. 이때 ReturnItem 함수를 호출해 아이템을 다시 오브젝트풀로 데리고 와서 없어진 것처럼 처리를 해줍니다.
더 생각해볼점
현재는 Init과 Create를 통해서 아이템을 생성하고 있으며 보면 같은 아이템만 생성하고 있습니다. 때문에 아이작같은 아이템이 많은 게임에서는 아이템들의 정보를 불러올 수 있는 방법들이 필요합니다.