Pull to refresh

Простейший пул в Unity

C# *Unity3D *Programming *Game development *
Awaiting invitation
Поскольку в 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();

В данном примере был показан пул без подгрузки элементов при их нехватке. Предполагаю, что ее можно реализовать так: указать минимально необходимый размер при создании стека или вообще его не заполнять, а перед перемещением объекта в лист добавлять один или несколько элементов в стек. Так стек будет постепенно расширяться при необходимости. Также можно сужать размер стека, сравнивая его размер через определенные промежутки времени и удаляя лишние элементы.
Tags:
Hubs:
You can’t comment this post because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.