Object Pooling (Оптимизация Instantiate)
Сделано при поддержке X-Forge
Определение
Объектный пул (object pool) — набор готовых к использованию объектов.
Когда системе требуется объект, он не создаётся, а берётся из пула. Когда объект больше не нужен, он не уничтожается, а возвращается в пул.
Когда системе требуется объект, он не создаётся, а берётся из пула. Когда объект больше не нужен, он не уничтожается, а возвращается в пул.
Применение
Применяется для повышения производительности, когда создание объекта в начале работы и уничтожение его в конце приводит к большим затратам.
Особенно заметно повышение производительности, когда объекты часто создаются-уничтожаются.
Особенно заметно повышение производительности, когда объекты часто создаются-уничтожаются.
В Unity
Абсолютно всем могу порекомендовать данный канал, рассказывает интересно и вполне отчетливо, я лично, смотрю без субтитров.
Можем его поблагодарить за самый простой код пулинга, который я совсем немного доработал.
Можем его поблагодарить за самый простой код пулинга, который я совсем немного доработал.
Код
Объяснять по-строчно - я не вижу смысла. Код крайне простой.
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);
}
}
Тест производительности
В итоге разница ~0.8 ms, (20 FPS), на 565 объектах, 0.001 период спавна/ уничтожения.
Результат не самый выдающиеся, особенно для такого количества объектов и периода.
Но оптимизация складывается за счет учета мелких факторов в самую, что ни на есть, весомую картину.
Результат не самый выдающиеся, особенно для такого количества объектов и периода.
Но оптимизация складывается за счет учета мелких факторов в самую, что ни на есть, весомую картину.
ну да