BerickCook правильно выразил эту идею. Оставьте расчеты там, где они есть, если они работают правильно сейчас.
Если вы можете выполнить вычисления раньше и уверены, что они вам не понадобятся в середине игры, сделайте это раньше. Остальное делай после загрузки. Если подсчет во время игры незаметен, вы можете сделать это там. Если в какой-то момент сложность развивается и вычисления становятся слишком тяжелыми, начинайте оптимизацию.
Но одна вещь: если ваши вычисления реализованы для запуска в середине игры, вы всегда можете принудительно выполнить их во время загрузки.
Есть множество решений:
- рассчитать / загрузить пути во время создания / загрузки уровня
- использовать второй поток для расчета путей
- оптимизировать ваши алгоритмы
- используйте прерываемую систему, если у вас нет доступа к потокам.
Я видел и использовал последний вариант в игре массового рынка. Просто убедитесь, что вы правильно сохранили все данные, необходимые для возобновления расчета, и регулярно проверяйте оставшееся время / операции во время расчета.
В зависимости от вашего случая система прерывания может дать предварительные и частичные решения, которые могут быть использованы событием до окончания расчета.
Редактировать : отвечая @Keeper
«Прерываемый алгоритм» был полезен только из-за ограничений, которые у нас были. В основном, мы смирились с отсутствием многопоточности.
В какой-то момент у нас была игра, в которой ИИ должен был вычислять большое количество ходов на основе нескольких словарей. Во время этого вычисления все анимации будут остановлены, потому что словари были расширены за счет большего количества данных, а набор данных, содержащий данные, был изменен и стал менее эффективным, когда игра была адаптирована для многопользовательской игры (где ИИ должен был взаимодействовать даже для ходов игрока). У нас был только один поток, доступный для игрового цикла (обязательным условием является то, что многоплатформенный код должен работать на всех поддерживаемых платформах). На этом этапе было решено нарушить алгоритм расчета, чтобы мы могли его прервать. Поэтому мы не могли просто использовать рекурсивную систему, которая существовала, поскольку переменные не могли быть сохранены. Функции были заменены объектами, которые просто содержали все необходимые переменные и указатели на родительские и дочерние объекты. Я не
- сохранить статус своих текущих вычислений
- прерывать либо в конце цикла, либо во время цикла (когда прерывается дочерний объект)
- выйти, когда время истекло
- возобновить с того места, где он остановился, либо перезапустить цикл с нужным индексом, либо вызвать дочерний объект, который в данный момент находится на вершине своего дочернего стека.
- очистить все, если вычисления прерваны
- дать лучший частичный результат.
Только самые дорогие операции были разбиты на отдельные объекты, и потребовалось некоторое время, чтобы найти нужные места, где мы могли бы остановить вычисления, но в итоге все работает очень хорошо.
Мы потеряли производительность, но воспринимаемая производительность была намного лучше для пользователя, поскольку анимации работали плавно на всех платформах, тогда все платформы могли бы использовать большие словари, не страдая от прерывистой анимации или зависаний. Также это позволило нам запускать несколько экземпляров параллельно, когда нам это понадобилось позже.
Конечно, теперь на iPhone и iPad игра не нуждается в этом, было бы идеально использовать второй поток. Но я подозреваю, что код все еще там.