Главная » Статьи » Программирование » Unity

Очередь объектов вместо их уничтожения

В каких случаях полезно применять очередь объектов вместо их уничтожения? Часто очереди применяют к снарядам (пулям, патронам), другими словами объектам у которых короткая жизни, но и которые требуются регулярно. В таких случаях очень неразумно использовать Destroy и потом заново создать копии объекта из префаба это отнимает много ресурсов и может замедлить игру.

Очередь объектов создать не сложно достаточно создать некий список или массив, в котором будет храниться очередь. Более подробно это рассмотрим на примере. Недавно используя свободное время, я создал небольшую 2D игру чем-то похожу на танки, в которые часто играл на приставках. На создание игры ушло около дня и как обычно я использовал очередь для снарядов. Очередь была создана общая на все игровые объекты игры, которые могут атаковать.

public class PoolBoltsScript : MonoBehaviour {

                public List<Attack> listAttack = new List<Attack>();

                public List<BoltScript> listBolt = new List<BoltScript>();

                public BoltScript prefabBolt;

                void doAttack(Attack attack) {

                                int n = listBolt.Count;

                                for (int i=0;i<n;i++) {

                                               var bolt = listBolt [i];

                                               if (bolt.enabledBolt == false) {

                                                               bolt.enabledBolt = true;

                                                               bolt.damage = attack.damage;

                                                               bolt.father = attack.currect;

                                                               bolt.velocity = attack.velocity;

                                                               bolt.gameObject.SetActive (true);

                                                               return;

                                               }

                                }

                                {

                                               var bolt = Instantiate (prefabBolt);

                                               bolt.damage = attack.damage;

                                               bolt.father = attack.currect;

                                               bolt.velocity = attack.velocity;

                                               bolt.gameObject.SetActive (true);

                                               listBolt.Add (bolt);

                                }

                }

 

                bool provList = false;

                float timeProv;

                List<BoltScript> listProv;

 

                void Update() {

                                if (listAttack.Count > 0) {

                                               doAttack (listAttack [0]);

                                               listAttack.RemoveAt (0);

                                }

                                int n = listBolt.Count;

                                if (n > 20) {

                                               if (provList == false) {

                                                               timeProv = UnityEngine.Time.time;

                                                               provList = true;

                                                               listProv = new List<BoltScript> ();

                                                               for (int i = 0; i < n; i++) {

                                                                               if (listBolt [i].enabledBolt == false) {

                                                                                              listProv.Add (listBolt [i]);

                                                                               }

                                                               }

                                               } else if (UnityEngine.Time.time - timeProv > 30f) {

                                                               n = listProv.Count;

                                                               for (int i = 0; i < n; i++) {

                                                                               if (listProv [i].enabledBolt == false) {

                                                                                              listBolt.Remove (listProv [i]);

                                                                               }

                                                               }

                                               }

                                } else if (provList == true) {

                                               provList = false;

                                }

                }

                               public int distanceMin = 10f;

                public void attackAdd(GameObjectInfo info, bool playerAttack, float damage) {

                                Vector2 target = new Vector2 (playerAttack ? distanceMin : -distanceMin, 0);

                                listAttack.Add (new Attack (info, target, damage));

                }

}

Постараюсь разобрать написанный скрипт по порядку. Класс «Attack» хранит необходимую информацию об атаке, конечно можно было использовать несколько обычных списков, но мне удобнее убирать все в один класс, мало ли нужно будет использовать такой же класс в другой игре, а он уже готов и методы тоже J . Класс «GameObjectInfo» просто содержит ссылки и методы общие для всех игровых объектов сцены, вы можете заменить его на GameObject, разницы не будет. Все запросы на таки добавляются через метод «attackAdd» как видно по коду снаряды у меня могут лететь только справа налево или наоборот. Как только в наш список попала новая атака (метод «Update») мы ищем в очереди свободный снаряд, если такого нет, то создаем новый и добавляем его к списку очереди. Когда снаряд исполнит свое предназначение он выключит себя сбросит необходимые параметры и через какое-то время снова вернется в строй.

В большинстве случаев пулы у меня являются общими для всех игровых объектов, которые используют объекты контролируемые пулом. Разумеется можно прикреплять пулы к определенным объектам и это может быть будет проще, но при этом стоит учитывать те факты, что объект может выключаться и включаться и поэтому нужно такие события обрабатывать в пуле.

В любом случае пулы использовать гораздо лучше чем уничтожать и создавать объекты. Даже, если вы создаете игру для мобильных устройств производительность повыситься, а количество оперативной памяти увеличиться не так сильно, но я не думаю, что об оперативной памяти на мобильных устройствах в наше время нужно беспокоится.

Категория: Unity | Добавил: Алексей (10.01.2017) | Автор: Фролов Алексей Алексеевич E
Просмотров: 769 | Теги: урок, Unity, Очердь, программирование, С#, Разработка игры, Пул | Рейтинг: 0.0/0
Всего комментариев: 0
avatar