Добавлен , опубликован

Dynamic Object Pooling

Небольшое дополнение к моей статье про объектный пул.

Применение

Динамический пул следует применять в двух случаях:
Когда точное количество существ в пуле неизвестно.
Когда неудачное создание существа вызовет сбой программы.
Но следует помнить, что всегда остается возможность создания бесконечного количества существ, которые могут повлиять на работу программы.

Код

  • Минимальные изменения от обычного пула.
source
using System;
using System.Collections.Generic;
using UnityEngine;
using Object = UnityEngine.Object;

namespace Assets.Scripts.Utility
{
    public class DynamicPool<T> where T : PooledItem
    {
        private readonly Queue<T> _available;
        private readonly T _prefab;
        private readonly Transform _parent;

        public DynamicPool(T prefab, int count, Transform parent = null)
        {
            _available = new Queue<T>();
            _prefab = prefab;
            _parent = parent;

            for (int i = 0; i < count; i++)
                AddEntityToPool();          
        }

        public void AddEntityToPool()
        {
            var entity = Object.Instantiate(_prefab, _parent);
            entity.gameObject.SetActive(false);
            entity.OnDestroy += item => _available.Enqueue(item as T);
            _available.Enqueue(entity);
        }

        public void Instantiate(out T instantiateEntity, Vector3 position, Quaternion rotation)
        {
            if (_available.Count > 0)
            {
                instantiateEntity = _available.Dequeue();
                instantiateEntity.transform.SetPositionAndRotation(position, rotation);
                instantiateEntity.gameObject.SetActive(true);
                return;
            }

            AddEntityToPool();
            Instantiate(out instantiateEntity, position, rotation);
        }
    }

    public abstract class PooledItem : MonoBehaviour
    {
        public event Action<PooledItem> OnDestroy;

        protected void ReturnToPool()
        {
            gameObject.SetActive(false);
            OnDestroy?.Invoke(this);
        }
    }
}
`
ОЖИДАНИЕ РЕКЛАМЫ...