게임/Unity

[Unity] 다중 오브젝트 풀링 (Multiful Object Pooling)

Nakuri 2022. 11. 6. 03:30
728x90

오브젝트 풀링(Object Pooling)

오브젝트의 생성과 파괴는 꽤 많은 성능을 잡아 먹는다.

생성은 메모리 할당과 리소스 로드, 파괴는 가비지 컬렉션이 동작하기 때문이다.

게임 실행 중 다량의 오브젝트가 생성 및 파괴가 된다면 프레임 드랍 등의 성능 문제가 발생할 것이다.

이를 방지하기 위해 사용하는 기법이 오브젝트 풀링이다.

오브젝트를 필요한 만큼 미리 생성해놓고 필요 할 때 사용하고 사용이 끝나면 다시 풀에 반납하는 방식이다.

다중 오브젝트 풀링(Object Pooling)

하지만 게임을 개발하다보면 오브젝트 풀이 필요한 경우가 생각보다 빈번하다. (투사체, 적, 타일 등)

기본적인 오브젝트 풀 코드에서는 이를 한번에 관리할 수가 없다.

이 문제를 해결하기 위해 여러 코드를 참고하여 다중 오브젝트 풀링(오브젝트 매니저)을 만들었다.

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

// 오브젝트 구분을 위한 타입
public enum EPoolObjectType
{
    Skill1,
    Skill2
}

// 오브젝트 풀
[Serializable]
public class PoolInfo
{
    public EPoolObjectType type;
    public int initCount;
    public GameObject prefab;
    public GameObject container;

    public Queue<GameObject> poolQueue = new Queue<GameObject>();
}

public class ObjectPoolManager : MonoBehaviour
{
    public static ObjectPoolManager Instance;

    // 오브젝트 풀 리스트
    [SerializeField] private List<PoolInfo> poolInfoList;

    private void Awake()
    {
        Instance = this;
        Initialize();
    }

    // 각 풀마다 정해진 개수의 오브젝트를 생성해주는 초기화 함수 
    private void Initialize()
    {
        foreach (PoolInfo poolInfo in poolInfoList)
        {
            for (int i = 0; i < poolInfo.initCount; i++)
            {
                poolInfo.poolQueue.Enqueue(CreatNewObject(poolInfo));
            }
        }
    }

    // 초기화 및 풀에 오브젝트가 부족할 때 오브젝트를 생성하는 함수
    private GameObject CreatNewObject(PoolInfo poolInfo)
    {
        GameObject newObject = Instantiate(poolInfo.prefab, poolInfo.container.transform);
        newObject.gameObject.SetActive(false);
        return newObject;
    }

    // ObjectType(Enum)으로 해당하는 PoolInfo를 반환해주는 함수
    private PoolInfo GetPoolByType(EPoolObjectType type)
    {
        foreach (PoolInfo poolInfo in poolInfoList)
        {
            if(type == poolInfo.type)
            {
                return poolInfo;
            }
        }
        return null;
    }

    // 오브젝트가 필요할 때 호출하는 함수
    public static GameObject GetObject(EPoolObjectType type)
    {
        PoolInfo poolInfo = Instance.GetPoolByType(type);
        GameObject objInstance = null;
        if (poolInfo.poolQueue.Count > 0)
        {
            objInstance = poolInfo.poolQueue.Dequeue();
        }
        else
        {
            objInstance = Instance.CreatNewObject(poolInfo);
        }
        objInstance.SetActive(true);
        return objInstance;
    }

    // 오브젝트 사용 후 다시 풀에 반환하는 함수
    public static void ReturnObject(GameObject obj, EPoolObjectType type)
    {
        PoolInfo poolInfo = Instance.GetPoolByType(type);
        poolInfo.poolQueue.Enqueue(obj);
        obj.SetActive(false);
    }
}

위 스크립트를 게임오브젝트(오브젝트 풀 매니저)에 추가면된다.

GameObject instanceObject = ObjectPoolManager.GetObject(poolType);

오브젝트를 생성할 때 위와 같은 형식으로 풀에서 가져오면 된다.

ObjectPoolManager.ReturnObject(gameObject, EPoolObjectType.Skill1);

오브젝트를 파괴할 때는 위와 같은 형식으로 풀에 반환해주면 된다.

 

  • Type : 풀을 구분하기 위한 열거형
  • Init Count : 처음 생성할 오브젝트의 수
  • Prefab : 복제할 오브젝트(프리팹)
  • Container : 오브젝트가 생성될 부모 게임오브젝트(인스펙터상 부모 오브젝트)

 

 

잘 작동한다!

참조

Unity Pool Manager Tutorial (Multiple Object Pooling)

[Unity3D] Programming - 오브젝트 풀링 기법 구현하기

'게임 > Unity' 카테고리의 다른 글

[Unity] Rider Debugging  (0) 2023.03.28
[Unity] \uFFFD Warning  (0) 2023.01.31
[Unity] RedRunnder 오픈소스 분석  (0) 2022.12.14
[Unity] 화면 외부에서 오브젝트 생성  (0) 2022.11.27