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

Object Pooling (Оптимизация Instantiate)

Сделано при поддержке X-Forge

Определение

Объектный пул (object pool) — набор готовых к использованию объектов.
Когда системе требуется объект, он не создаётся, а берётся из пула. Когда объект больше не нужен, он не уничтожается, а возвращается в пул.

Применение

Применяется для повышения производительности, когда создание объекта в начале работы и уничтожение его в конце приводит к большим затратам.
Особенно заметно повышение производительности, когда объекты часто создаются-уничтожаются.

В Unity


Marcos , используется для трассеров и эффектов попадания.
Абсолютно всем могу порекомендовать данный канал, рассказывает интересно и вполне отчетливо, я лично, смотрю без субтитров.
Можем его поблагодарить за самый простой код пулинга, который я совсем немного доработал.

Код

Объяснять по-строчно - я не вижу смысла. Код крайне простой.


pool code
using System;
using System.Collections.Generic;
using UnityEngine;
using Object = UnityEngine.Object;

public class Pool<T> where T : PooledItem
{
    private readonly Queue<T> _available;

    public Pool(T prefab, int count, Transform parent = null)
    {
        _available = new Queue<T>();
        for (int i = 0; i < count; i++)
        {
            var entity = Object.Instantiate(prefab, parent);
            entity.gameObject.SetActive(false);
            entity.OnDestroy += item => _available.Enqueue(item as T);
            _available.Enqueue(entity);
        }
    }

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

        instantiateEntity = null;
        return false;
    }
}

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

    protected void ReturnToPool()
    {
        gameObject.SetActive(false);
        OnDestroy?.Invoke(this);
    }
}

Тест производительности

С пулингом
Time: 0.13 ms
Без пулинга
Time: 0.95 ms
В итоге разница ~0.8 ms, (20 FPS), на 565 объектах, 0.001 период спавна/ уничтожения.
Результат не самый выдающиеся, особенно для такого количества объектов и периода.
Но оптимизация складывается за счет учета мелких факторов в самую, что ни на есть, весомую картину.
`
ОЖИДАНИЕ РЕКЛАМЫ...
2
37
2 года назад
2
Что за непрофессионализм считать в fps? Есть конкретно бенчмарки лоада ядра хотябы? В целом, технология многим известна и много где используется.
0
22
2 года назад
0
ScorpioT1000, не раз уже упрекали мой профайлинг по фпс, сам знаю, что это не показатель, но тут я считаю вполне оправдано для показа преимущества.
0
48
2 года назад
0
это ещё называют кешированием
0
37
2 года назад
0
N7 Molot, скорее буфер, чем кеш. Любой кеш можно очистить без вреда для бизнес-логики работы.
0
48
2 года назад
0
ScorpioT1000:
ну да

а, и профайлер лучше, чем какой то левый бенч. Профайлер показывает именно то, как юнити нагружает систему.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.