[Design Pattern] 10. 오브젝트 풀(Object Pool)

업데이트:

카테고리:

태그: ,




Object Pool

Object Pool






Object Pool

프레임 속도유지, 자주 생성되는 요소를 일부 메모리에 예약하는게 좋음
메모리에서 없애는 대신 다시 사용할 수 있도록 오브젝트 풀에 추가
엔티티의 새로운 인스턴스를 로드하는 초기의 초기화 비용이 들지 않음

object pool 객체의 풀을 관리, 객체 생성, 관리, 파기
reusable pool : 실제로 재사용될 객체, object pool 이 여기 객체를 관리
clien : 클라이언트는 필요할 때 오브젝트풀에서 reuablepool 객체를 요청, 사용 후 다시 풀에 반환

장점
  1. 예측할 수 있는 메모리 사용
  2. 성능 향상

단점
  1. 이미 c# 이 메모리 최적화가 뛰어나서 굳이 필요없다? 썰
  2. 예측 불가능한 객체 상태



DroneObjectPool
using UnityEngine;
using UnityEngine.Pool;

public class DroneObjectPool : MonoBehaviour
{
    public int maxPoolSize = 10;
    public int stackDefaultCapacity = 10;

    // 필요할 떄 오브젝트 풀을 생성함
    public IObjectPool<Drone> Pool 
    {
        get 
        {
            if (_pool == null)
                _pool = 
                    new ObjectPool<Drone>(
                        CreatedPooledItem, 
                        OnTakeFromPool, 
                        OnReturnedToPool, 
                        OnDestroyPoolObject, 
                        true, 
                        stackDefaultCapacity,
                        maxPoolSize);
            return _pool;
        }
    }

    private IObjectPool<Drone> _pool;

    private Drone CreatedPooledItem() 
    {
        var go = 
            GameObject.CreatePrimitive(PrimitiveType.Cube);
        
        Drone drone = go.AddComponent<Drone>();
        
        go.name = "Drone";
        drone.Pool = Pool;
        
        return drone;
    }

    // 드론이 풀로 돌아올 때 호출됨
    private void OnReturnedToPool(Drone drone) 
    {
        drone.gameObject.SetActive(false);
    }

    // 드론이 풀에서 꺼내질 때 호출됨
    private void OnTakeFromPool(Drone drone) 
    {
        drone.gameObject.SetActive(true);
    }

    // 드론 오브젝트를 파괴할 때
    private void OnDestroyPoolObject(Drone drone) 
    {
        Destroy(drone.gameObject);
    }

    // 무작위 수의 드론을 생성하고 위치를 설정할 때
    public void Spawn() 
    {
        var amount = Random.Range(1, 10);
        
        for (int i = 0; i < amount; ++i) {
            var drone = Pool.Get();
            
            drone.transform.position = 
                Random.insideUnitSphere * 10;
        }
    }
}
DroneObjectPool
using UnityEngine;
using UnityEngine.Pool;

public class DroneObjectPool : MonoBehaviour
{
    public int maxPoolSize = 10;
    public int stackDefaultCapacity = 10;

    // 필요할 떄 오브젝트 풀을 생성함
    public IObjectPool<Drone> Pool 
    {
        get 
        {
            if (_pool == null)
                _pool = 
                    new ObjectPool<Drone>(
                        CreatedPooledItem, 
                        OnTakeFromPool, 
                        OnReturnedToPool, 
                        OnDestroyPoolObject, 
                        true, 
                        stackDefaultCapacity,
                        maxPoolSize);
            return _pool;
        }
    }

    private IObjectPool<Drone> _pool;

    private Drone CreatedPooledItem() 
    {
        var go = 
            GameObject.CreatePrimitive(PrimitiveType.Cube);
        
        Drone drone = go.AddComponent<Drone>();
        
        go.name = "Drone";
        drone.Pool = Pool;
        
        return drone;
    }

    // 드론이 풀로 돌아올 때 호출됨
    private void OnReturnedToPool(Drone drone) 
    {
        drone.gameObject.SetActive(false);
    }

    // 드론이 풀에서 꺼내질 때 호출됨
    private void OnTakeFromPool(Drone drone) 
    {
        drone.gameObject.SetActive(true);
    }

    // 드론 오브젝트를 파괴할 때
    private void OnDestroyPoolObject(Drone drone) 
    {
        Destroy(drone.gameObject);
    }

    // 무작위 수의 드론을 생성하고 위치를 설정할 때
    public void Spawn() 
    {
        var amount = Random.Range(1, 10);
        
        for (int i = 0; i < amount; ++i) {
            var drone = Pool.Get();
            
            drone.transform.position = 
                Random.insideUnitSphere * 10;
        }
    }
}
Drone
using UnityEngine;
using UnityEngine.Pool;
using System.Collections;

public class Drone : MonoBehaviour 
{
    public IObjectPool<Drone> Pool { get; set; }

    public float _currentHealth;

    [SerializeField] 
    private float maxHealth = 100.0f;
    [SerializeField] 
    private float timeToSelfDestruct = 3.0f;

    void Start() 
    {
        _currentHealth = maxHealth;
    }
    
    void OnEnable() 
    {
        AttackPlayer();
        StartCoroutine(SelfDestruct());
    }

    private void OnDisable() 
    {
        ResetDrone();
    }

    IEnumerator SelfDestruct() {
        yield return new WaitForSeconds(timeToSelfDestruct);
        TakeDamage(maxHealth);
    }
    
    private void ReturnToPool() {
        Pool.Release(this);
    }
    
    private void ResetDrone() {
        _currentHealth = maxHealth;
    }

    public void AttackPlayer() {
        Debug.Log("Attack player!");
    }

    public void TakeDamage(float amount) {
        _currentHealth -= amount;
        
        if (_currentHealth <= 0.0f)
            ReturnToPool();
    }
}
ClientObjectPool
using UnityEngine;

public class ClientObjectPool : MonoBehaviour
{
    private DroneObjectPool _pool;
    
    void Start()
    {
        _pool = gameObject.AddComponent<DroneObjectPool>();
    }

    void OnGUI()
    {
        if (GUILayout.Button("Spawn Drones"))
            _pool.Spawn();
    }
}







잡담, 정리

  • 디자인 패턴은 애초에 특정 문제를 해결하기 위해 고려된 것.(성능, 메모리 사용 고려)
  • 추가 내용 정리




[C#] 디자인 패턴 (Design Pattern)
TOP


📔

댓글남기기