Время загрузки до игры и время загрузки

9

Я разрабатываю игру, в которую включен случайный лабиринт.
Есть некоторые искусственные существа, скрывающиеся в лабиринте. И я хочу, чтобы они пошли каким-то путем по форме лабиринтов.

Теперь у меня есть две возможности реализовать это, первый способ (который я использовал) состоит в том, чтобы вычислить несколько желаемых скрытых путей, как только лабиринт создан.
Второе - это вычисление пути, которое когда-то нужно было вычислить, когда существо начинает его скрывать.

Моя главная проблема - время загрузки. Если я вычисляю много путей при создании лабиринта, время предварительной загрузки немного велико, поэтому я подумал о том, чтобы рассчитать их при необходимости.
На данный момент игра не «тяжелая», поэтому вычисление путей в середине игры не заметно, но я боюсь, что когда-нибудь это станет более сложным.

Любые предложения, комментарии, мнения, будут полезны.

Редактировать:

На данный момент, пусть pбудет числом предварительно рассчитанных путей, у существа есть вероятность 1/pвыбрать новый путь (что означает расчет пути) вместо существующего.
Разумеется, существо не начинает патрулирование, пока путь не будет полностью рассчитан, поэтому не нужно беспокоиться о том, что его убьют в процессе.

смотритель
источник
8
На данный момент, это было бы предварительно оптимизировать. Я бы оставил все как есть, пока не возникнет проблема.
Джон Макдональд
3
И если немного поразмыслить с @JohnMcDonald, если вы можете рассчитать эти пути в середине игры, и это не заметно, насколько способствующим фактором они могут быть во время загрузки?
Джеймс

Ответы:

6

BerickCook правильно выразил эту идею. Оставьте расчеты там, где они есть, если они работают правильно сейчас.

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

Но одна вещь: если ваши вычисления реализованы для запуска в середине игры, вы всегда можете принудительно выполнить их во время загрузки.

Есть множество решений:

  • рассчитать / загрузить пути во время создания / загрузки уровня
  • использовать второй поток для расчета путей
  • оптимизировать ваши алгоритмы
  • используйте прерываемую систему, если у вас нет доступа к потокам.

Я видел и использовал последний вариант в игре массового рынка. Просто убедитесь, что вы правильно сохранили все данные, необходимые для возобновления расчета, и регулярно проверяйте оставшееся время / операции во время расчета.

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


Редактировать : отвечая @Keeper

«Прерываемый алгоритм» был полезен только из-за ограничений, которые у нас были. В основном, мы смирились с отсутствием многопоточности.

В какой-то момент у нас была игра, в которой ИИ должен был вычислять большое количество ходов на основе нескольких словарей. Во время этого вычисления все анимации будут остановлены, потому что словари были расширены за счет большего количества данных, а набор данных, содержащий данные, был изменен и стал менее эффективным, когда игра была адаптирована для многопользовательской игры (где ИИ должен был взаимодействовать даже для ходов игрока). У нас был только один поток, доступный для игрового цикла (обязательным условием является то, что многоплатформенный код должен работать на всех поддерживаемых платформах). На этом этапе было решено нарушить алгоритм расчета, чтобы мы могли его прервать. Поэтому мы не могли просто использовать рекурсивную систему, которая существовала, поскольку переменные не могли быть сохранены. Функции были заменены объектами, которые просто содержали все необходимые переменные и указатели на родительские и дочерние объекты. Я не

  • сохранить статус своих текущих вычислений
  • прерывать либо в конце цикла, либо во время цикла (когда прерывается дочерний объект)
  • выйти, когда время истекло
  • возобновить с того места, где он остановился, либо перезапустить цикл с нужным индексом, либо вызвать дочерний объект, который в данный момент находится на вершине своего дочернего стека.
  • очистить все, если вычисления прерваны
  • дать лучший частичный результат.

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

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

Конечно, теперь на iPhone и iPad игра не нуждается в этом, было бы идеально использовать второй поток. Но я подозреваю, что код все еще там.

койот
источник
Спасибо, это звучит очень интересно. Не могли бы вы рассказать о понятии "система прерывания" (почему и как). (гуглить это было не очень полезно ..). Я добавлю некоторые детали к вопросу.
Хранитель
@Keeper Надеюсь, я ответил на ваш вопрос о прерываемой части. Это трудная задача, но она не актуальна в большинстве современных систем.
Койот
Хотя сейчас я не собираюсь использовать этот метод, вы открыли мне глаза на что-то новое. Ваш ответ заслуживает принятия.
Хранитель
8

На данный момент, так как вычисление путей в середине игры незаметно, это идеальный подход. Если / когда он достигает точки, где игровой процесс прерывается вычислениями, тогда переключите его на пересчет путей до загрузки уровня.

Более длительные начальные времена загрузки простительны, но случайные колебания FPS во время игры обычно не допускаются.

BerickCook
источник
2

Одна возможность, если вам это нужно, - это перенести вычисления во второй поток, поскольку почти каждый ПК имеет более одного ядра ЦП.

Основной процесс будет:

  • Когда существо запрашивает путь, добавьте запрос в очередь запросов с безопасным потоком и подайте сигнал потоку.
  • Существо бездействует, ожидая, пока поток извлечет запись из этой очереди, обработает ее и поместит в завершенный список.
  • Каждый кадр проверяет заполненный список из основного потока и назначает завершенные пути существам.

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

Адам
источник
2
Если вы не хотите вводить многопоточность, вы также можете постепенно вычислить свой путь (например, рассчитать несколько шагов в каждом кадре).
Bummzack