[UNITY C#] ObjectPool 구현

2022. 2. 4. 18:00·UNITY/Script
반응형

ObjectManager.cs

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

/// <summary>
/// ObjectManager에서 관리할 오브젝트 리스트를 나타냅니다.
/// </summary>
public enum ObjectList {
    Object1, Object2
}

/// <summary>
/// ObjectPool을 관리하는 클래스입니다.
/// </summary>
public class ObjectManager : MonoBehaviour
{
    static ObjectManager instance = null; 
    public static ObjectManager Instance { // ObjectManager 싱글톤을 구현합니다. ObjectManager.Instance. 형식으로 접근합니다.
        get {
            if(instance == null){
                instance = FindObjectOfType<ObjectManager>();
            }
            return instance;
        }
    }

    [Header("Prefab")]
    [SerializeField] GameObject object1_prefab = null;
    Queue<GameObject> object1_queue = new Queue<GameObject>();
    [SerializeField] GameObject object2_prefab = null;
    Queue<GameObject> object2_queue = new Queue<GameObject>();
    // 새로운 Prefab을 등록하는 단위
    // [SerializeField] GameObject (오브젝트 이름)_prefab = null;
    // Queue<GameObject> (오브젝트 이름)_queue = new Queue<GameObject>();
    // ...

    /// <summary>
    /// 필요한 GameObject들을 미리 생성해 ObjectPool에 저장합니다.
    /// </summary>
    void Start() { 
        CreateObject(ObjectList.Object1, 5);
        CreateObject(ObjectList.Object2, 10);
    }

    /// <summary>
    /// Queue를 불러옵니다.
    /// </summary>
    /// <param name="object_target">불러올 오브젝트 Queue의 ObjectList입니다.</param>
    Queue<GameObject> GetQueue(ObjectList object_target) { 
        try {
            switch(object_target) {
                case ObjectList.Object1 : return object1_queue;
                case ObjectList.Object2 : return object2_queue;
                default : throw new Exception("Queue가 존재하지 않습니다.");
            }
        } catch {
            return null;
        }
    }
    /// <summary>
    /// Prefab을 불러옵니다.
    /// </summary>
    /// <param name="object_target">불러올 오브젝트 Prefab의 ObjectList입니다.</param>
    GameObject GetPrefab(ObjectList object_target) { 
        try {
            switch(object_target) {
                case ObjectList.Object1 : return object1_prefab;
                case ObjectList.Object2 : return object2_prefab;
                default : throw new Exception("Prefab이 존재하지 않습니다.");
            }
        } catch {
            return null;
        }
    }

    /// <summary>
    /// <para>GameObject를 생성합니다.</para>
    /// <para>(처음 실행하거나 Queue에 가져올 GameObject가 없을 경우 이 메서드를 통해 새로운 GameObject를 생성합니다)</para>
    /// </summary>
    /// <param name="object_target">생성할 오브젝트의 ObjectList입니다.</param>
    /// <param name="repeat">생성할 오브젝트의 개수입니다.</param>
    void CreateObject(ObjectList object_target, byte repeat = 1) { 
        GameObject prefab_target = GetPrefab(object_target);
        Queue<GameObject> queue_target = GetQueue(object_target);

        if(prefab_target != null && queue_target != null) {
            while(repeat-- > 0) {
                GameObject object_new = Instantiate(prefab_target);
                object_new.transform.SetParent(transform);
                object_new.SetActive(false);

                queue_target.Enqueue(object_new);
            }
        }
    }

    /// <summary>
    /// <para>오브젝트를 불러옵니다.</para>
    /// </summary>
    /// <param name="object_target">불러올 오브젝트의 ObjectList입니다.</param>
    /// <param name="setActive">불러올 오브젝트의 SetActive옵션입니다.</param>
    public GameObject GetObject(ObjectList object_target, bool setActive = true) { 
        Queue<GameObject> queue_target = GetQueue(object_target);

        if(queue_target != null) {
            if(queue_target.Count <= 0) {
                CreateObject(object_target);
            }
            GameObject object_return = queue_target.Dequeue();

            object_return.transform.SetParent(null);
            object_return.SetActive(setActive);

            return object_return;
        } else {
            return null;
        }
    }

    /// <summary>
    /// <para>오브젝트를 반환합니다.</para>
    /// </summary>
    /// <param name="object_target">반환할 오브젝트의 ObjectList입니다.</param>
    /// <param name="object_return">반환할 GameObject입니다.</param> 
    public void ReturnObject(ObjectList object_target, GameObject object_return) {
        if(object_return) {
            object_return.transform.SetParent(transform);
            object_return.SetActive(false);

            GetQueue(object_target).Enqueue(object_return);
        } else {
            throw new ArgumentNullException("반환하는 GameObject가 지정되지 않았습니다.");
        }
    }
}

 

다음과 같은 오브젝트 풀을 관리하는 스크립트를 작성합니다.

오브젝트 풀로 사용할 GameObject에 해당 스크립트를 추가하고 각 Prefab을 할당합니다.

Play 모드에 진입하면 오브젝트 풀이 활성화됩니다.

(오브젝트 풀에 있는 오브젝트들은 순환하면서 사용됩니다.)

 

Object 불러오기

GameObject object1 = ObjectManager.Instance.GetObject(ObjectList.Object1);

GetObject는 Instantiate대신 사용하는 GameObject 로드 메서드입니다.

(GameObject를 불러오고 나서 부모 오브젝트, 스케일, 위치 등은 직접적인 수정이 필요합니다.)
(UI(RectTransform) GameObject를 불러올때 반드시 transform.SetParent(... , false), transform.localScale = new Vector3(1f, 1f, 1f)를 해주어야 합니다.)

 

Object 반환하기

ObjectManager.Instance.ReturnObject(ObjectList.Object1, gameObject);

ReturnObject는 Destroy대신 사용하는 GameObject 삭제 메서드입니다.

(위의 경우 GameObject를 반환할때 gameObject의 ObjectList를 정확하게 지정해 주어야합니다.)

 

반응형
'UNITY/Script' 카테고리의 다른 글
  • [UNITY C#] 원근감있는 배경 : 패럴랙스 스크롤링(Parallax Scrolling) 구현
  • [UNITY C#] Unity Attribute 정리
  • [UNITY C#] SceneManagement 씬 전환 구현
  • [UNITY C#] 게임 데이터 직렬화(Serialize) 저장 및 로드 구현
HYEOKJUN
HYEOKJUN
프로그래밍 관련 수업이나 웹 사이트에서 직접 얻은 정보를 공유하는 블로그입니다. (일부 잘못된 정보가 포함될 수 있습니다)
  • HYEOKJUN
    HYEOKJUN
    HYEOKJUN
  • 전체
    오늘
    어제
    • 분류 전체보기 (53)
      • UNITY (18)
        • Tool (9)
        • Script (9)
      • C | C++ (20)
        • Basic (11)
        • STL (8)
        • ETC (1)
      • C# (1)
        • Basic (0)
        • ETC (1)
      • Python (8)
        • Basic (7)
        • Library (1)
        • ETC (0)
      • WEB (2)
        • Basic (2)
      • Skill (0)
        • 자료구조 (0)
      • Workspace (0)
      • ETC (4)
  • 블로그 메뉴

    • 인기 글

    • 태그

      red-black tree
      Python
      반복문
      Package
      조건문
      std
      변수
      자료형
      queue
      포인터
      while
      컨테이너
      Localization
      식별자
      C
      Unity
      C#
      stack
      C++
      vector
    • 최근 글

    • hELLO· Designed By정상우.v4.10.3
    HYEOKJUN
    [UNITY C#] ObjectPool 구현
    상단으로

    티스토리툴바