ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 유니티 2D 아이템 드랍 오브젝트 폴링으로 구현하기
    쾌락없는 책임 (공부)/Unity 2021. 5. 8. 20:57
    반응형

    오브젝트 폴링

     몬스터가 아이템 드롭을 하는걸 계속 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를 통해서 아이템을 생성하고 있으며 보면 같은 아이템만 생성하고 있습니다. 때문에 아이작같은 아이템이 많은 게임에서는 아이템들의 정보를 불러올 수 있는 방법들이 필요합니다.

    반응형

    댓글

Designed by Tistory.