본문 바로가기
Unity 유니티 기초강의

유니티 풀링 Pooling 만들기 최적화 재활용

by 만사오케이프로 2022. 6. 4.
반응형

유니티 기본적인 풀링 구현 방법입니다. 가장쉽고 기본적인 방법으로 만들었습니다.

유니티에서 총알이나 미사일등 자주 생성후 삭제하는 경우 메모리 릭이 발생할 경우가 있습니다.

가비지에서 메모리를 한번씩 정리할때 느려집니다. 그래서 풀링을 사용하면 가비지가 할일이 줄어 원활한 게임 플레이에 도움이됩니다.

 

 

제작방법

1)풀링메니저 만들기

빈오브젝트에 PoolMananger.cs 스크립트를 넣어서 사용합니다. (마지막에 풀코드 있습니다)

넣으면 리스트가 있습니다.

+를 누르면 Prefab, InitCount가 있는 요소가 추가됩니다. Prefab에는 풀링할 오브젝트를 넣어줍니다.

Init Count에는 미리 생성해 놓을에는 초기 생성 개수를 정할수 있습니다.

예를

Prefab안에 Effect Prefab인 Bubble 2를 넣었고 InitCount 3를 넣습니다. 

Play실행시 PoolManager.cs를 넣은 오브젝트 하위에 InitCount 개수만큼 프리팹이 생성되는걸 확인할수 있습니다.

2)풀링사용 방법입니다.

PoolMananger.instance.GetSpawn(사용할 프리팹 이름); 을 넣어주면 풀링된 오브젝트가져올수 있습니다.

 

var prefrab =  PoolMananger.instance.GetSpawn("Bubbles 2");
prefrab.transform.position = Vector3.zero;

3)오브젝트 사용후 비활성화 해주어야 나중에 풀링메니저에서 사용할수 있습니다.

이펙트에 활성화 후 몇 초뒤 오브젝트를 비활성화 해주는 코드를 Effect Prefab에 추가합니다. 

 

using System.Collections;
using UnityEngine;

public class EffectItem : MonoBehaviour
{
    public float destoryTime; //public으로 하여 인스펙트에서 수정하게 해줄수 있게 한다.
    private void OnEnable()
    {
        StartCoroutine(DelayDestory());
    }

    IEnumerator DelayDestory()
    {
        yield return new WaitForSeconds(destoryTime); //destoryTime 이후 오브젝트 꺼준다.
        this.gameObject.SetActive(false);
    }
}

 

Tip)

만약 풀링오브젝트들이 다 사용하고 있는겨우(오브젝트 활성화) 더 생성합니다.

예를 들어 버블 오브젝트 3개 사용하고 있을때 더 사용하면 1개를 자동으로 생성하여 총 4개가 됩니다.

 

 

using System;
using UnityEngine;
using System.Collections.Generic;

[Serializable]
public class PoolItemData
{
    public GameObject prefab;
    public int initCount = 5;
    public List<GameObject> listItem;
}
public class PoolMananger : Singleton<PoolMananger>
{
    public List<PoolItemData> listPool = new List<PoolItemData>();

    void Awake()
    {
        AddObjectsToPool();
    }

    void AddObjectsToPool()
    {
        foreach (var pool in listPool)
        {
            for (int i = 0; i < pool.initCount; i++)
            {
                var ob = Instantiate(pool.prefab, transform);
                pool.listItem.Add(ob);
                ob.transform.localPosition = Vector3.zero;
                ob.SetActive(false);
            }
        }
    }

    public GameObject GetSpawn(string prefabName)
    {
        foreach (var pool in listPool)
        {
            if (pool.prefab.name.Equals(prefabName))
            {
                if (pool.listItem != null)
                {
                    foreach (var item in pool.listItem)
                    {
                        if (!item.activeSelf)
                        {
                            item.SetActive(true);
                            return item;
                        }
                    }
                    
                    var ob = Instantiate(pool.prefab, transform);
                    pool.listItem.Add(ob);
                    ob.transform.localPosition = Vector3.zero;
                    ob.SetActive(true);
                    
                    return ob;
                }
            }
        }
        return null;
    }
}

 

반응형

댓글