본문 바로가기
개발/Unity 내일배움캠프 TIL

Unity 오브젝트 풀

by 석시 2023. 9. 8.



오브젝트 풀을 쓰는 이유

유니티에서는 프리팹을 만들어 개체를 생성할 때 생성함수 Instantiate()와 삭제함수 Destroy()를 제공해준다.

하지만 이 두가지의 함수를 너무 자주 사용하게 되면 물리적인 메모리 상에서 파편화된 메모리 (찌꺼기 메모리)가 계속해서 발생하게 되면서 성능에 악영향을 줄 수 있다.

이러한 문제를 해결하기 위해 오브젝트 풀링 (Object Pooling)이라는 것을 사용한다.

직접 한 번 만들어보는 시간을 가져보자.

나는 골드메탈님의 유튜브 강좌를 참고하여 몬스터를 소환하는 오브젝트 풀을 제작해보았다.

오브젝트 풀링🏊으로 소환하기 [유니티 뱀서라이크 06]
플레이어 주변에 수많은 적을 소환하는, 뱀서라이크의 묘미를 직접 만들어보는 시간입니다. 오브젝트 풀링을 간단하게 만들 수 있는 방법을 바로 다루는 편이다보니 코드 하나하나 상세하게 설명하면서 강좌 길이가 좀 길어진 점 양해 바랍니다.😌 📚 뱀서라이크 개발 채널 https://www.youtube.com/playlist?list=PLO-mt5Iu5TeZF8xMHqtT_DhAPKmjF6i3x 🚀 오브젝트 풀링 코드 https://blog.naver.com/gold_metal/222960275623 📖 챕터 01 00:00 프리펩 만들기 02 03:22 오브젝트 풀 만들기 03 13:15 풀링 함수 작성 04 23:56 풀링 사용해보기 05 31:21 주변에 생성하기 #유니티강좌 #유니티기초 #뱀서라이크 #뱀파이어서바이버
https://youtu.be/A7mfPH8jyBE?si=pUGR5aqsJeM-Q0K-


오브젝트 풀 생성

일단 Pool을 관리해주는 오브젝트를 만들어주자.

빈 오브젝트를 생성하고 이름을 PoolManager로 바꾸자.

PoolManager라는 이름의 스크립트도 하나 만들어서 오브젝트에 붙여주자.

스크립트에 구현할 내용은 다음과 같다.

  • 프리팹들을 보관할 변수
  • 풀 담당을 하는 리스트들 (프리팹 하나 당 한 개씩)

다음과 같이 작성하였다.


public class PoolManager : MonoBehaviour
{
    // 프리팹들을 보관할 변수
    public GameObject[] prefabs;

    // 풀 담당을 하는 리스트들
    private List<GameObject>[] _pools;

    private void Awake()
    {
        _pools = new List<GameObject>[prefabs.Length];

        for (int index = 0; index < _pools.Length; ++index)
            _pools[index] = new List<GameObject>();
    }
}


풀링용 함수 작성

다른 오브젝트에서 이렇게 만든 오브젝트 풀에 접근해서 풀 안에 있는 GameObject를 마치 Instantiate 하듯이 받아올 수 있어야 한다.

이러한 Instantiate를 대체하는 Get 함수를 작성해야 한다.

함수는 다음과 같이 작동해야 한다.

  1. 선택한 풀의 비활성화 되어 있는 GameObject 접근
  1. 발견하면 해당 GameObjectreturn 해줌
  1. 발견하지 못하면 (풀의 오브젝트가 전부 활성화 되어 있으면)

    새롭게 생성하고 풀에 넣은 뒤 그 GameObjectreturn

코드로 작성하면 다음과 같다.


public GameObject Get(int index)
{
    // 선택한 풀의 비활성화 되어 있는 GameObject 접근
    foreach (GameObject item in _pools[index])
        if (item.activeSelf == false) {
            // 발견하면 그 GameObject를 return
            item.SetActive(true);
            return item;
        }

    // 발견하지 못하면
    // 새롭게 생성하고 풀에 넣은 뒤 그것을 return
    GameObject newItem = Instantiate(prefabs[index], transform);
    _pools[index].Add(newItem);

    return newItem;
}

이제 해당 함수 Get을 마치 Instantiate처럼 쓸 수 있는 것이다.

Destroy는 어떻게 하냐구요?

그냥 해당 GameObject를 비활성화만 해주면 된다!

Instantiate 없이도 아주 잘 작동한다.


Uploaded by N2T