Поскольку в Unity операции создания и удаления объектов являются затратными и при их использовании могут появляться микрофризы, по крайней мере, на мобильных устройствах, то желательно создавать объекты заранее и уже потом манипулировать менее дорогостоящими операциями. В данном примере будет описан простейший пул без подгрузки элементов при их нехватке, нехватка компенсируется созданием заранее достаточно большого количества объектов. Таким образом, мы избавляется от микрофризов ценой дольшей загрузки в начале и большего потребления памяти.
Данный пример визуально можно представить так, допустим, что у нас есть стол на котором стоит безразмерная подставка для тарелок, а перед нами кирпичная стена. В начале мы заполняем подставку необходимым количеством тарелок, это будет стек тарелок. Потом мы с определенной периодичностью берем из подставки-стека тарелки по одной с верху и кидаем в стену, при этом разбитые тарелки возвращаются обратно в стек. Пространство между нами и стеной это тоже контейнер. Предположим, что некоторые тарелки мы сбиваем из ружья, следовательно разбиваются и, соответственно, возвращаются они явно не в том порядке, в котором были выпущены. Значит это пространство нельзя реализовать в виде еще одного стека. Здесь нужен контейнер с произвольным доступом, поэтому возьмем List.
Stack<GameObject> plate_stand_pool; //Пул тарелок
List<GameObject> plate_fly_pool; //Пул взятых тарелок
Дальше заполняем пул.
for (int i = 0; i < 100; i++)
{
plate_stand_pool.Push(Instantiate(plate));
plate_stand_pool.Peek().SetActive(false); //Можно сразу настроить
}
Там, где нужно берем объект из пула.
plate_fly_pool.Add(plate_stand_pool.Pop());
plate_fly_pool[plate_fly_pool.Count - 1].SetActive(true);
Возвращаем в пул.
for (int i = 0; i < plate_fly_pool.Count; i++)
{
if (plate_fly_pool[i].transform.position.x > 0.0f)
{
plate_stand_pool.Push(plate_fly_pool[i]);
plate_stand_pool.Peek().SetActive(false);
plate_fly_pool.RemoveAt(i);
}
}
Также, если требуется, можно сразу переместить все объекты обратно в стек и очистить лист, вместо удаления элементов листа из цикла.
for (int i = 0; i < plate_fly_pool.Count; i++)
{
if (plate_fly_pool[i].transform.position.x > 0.0f)
{
plate_stand_pool.Push(plate_fly_pool[i]);
plate_stand_pool.Peek().SetActive(false);
}
}
plate_fly_pool.Clear();
В данном примере был показан пул без подгрузки элементов при их нехватке. Предполагаю, что ее можно реализовать так: указать минимально необходимый размер при создании стека или вообще его не заполнять, а перед перемещением объекта в лист добавлять один или несколько элементов в стек. Так стек будет постепенно расширяться при необходимости. Также можно сужать размер стека, сравнивая его размер через определенные промежутки времени и удаляя лишние элементы.
Автор: мистер Олимпия