Масштабируемость
Есть несколько способов оптимизации для этой ситуации. С одной стороны, вам, возможно, не придется делить на несколько игровых кадров. В некоторой степени кажется, что масштабируемость является проблемой. 100 единиц, по крайней мере, в 100 раз дороже, чем 1 единица.
Итак, как мы можем сделать путь более оптимизированным для масштабируемости? Ну, это зависит от вашего игрового дизайна. Я собираюсь (возможно, ошибочно) предположить типичный сценарий RTS. Несколько групп юнитов, каждая из которых находится относительно близко друг к другу. Путь решения для многих единиц в непосредственной близости будет довольно похожим. Модули могут запросить маршрутизацию от какого-либо решателя маршрутизации. Этот решатель маршрутизации может хранить таблицу недавних запросов маршрутизации и их решений и избегать расчета одного и того же вывода из одного и того же ввода несколько раз. Это называется памятка .
Еще одним дополнением к этому может быть создание иерархии из вашей сетки или графика. Сначала решите более простой график, а затем переключитесь на более подробный график. Несколько устройств могут использовать один и тот же путь с низким разрешением, пользуясь преимуществом запоминания, но каждый рассчитывает свой собственный путь с высоким разрешением индивидуально, если пути с высоким разрешением слишком многочисленны для разумного запоминания.
Многокадровые вычисления
Что касается попыток разделения вычислений между кадрами, я могу придумать несколько подходов.
Если вы хотите выбрать многопоточный маршрут, вы можете использовать модель объединения рабочих потоков. Каждый раз, когда юнит запрашивает путь, он ставится в очередь для решения. Когда рабочий поток свободен, ему назначается задача для решения. Когда поток решает задачу, у вас может быть обратный вызов для информирования устройства или запрос модуля, если задача каким-либо образом завершена, скорее всего, запрашивается каждый кадр.
Если нет динамических препятствий или они обрабатываются отдельно, вы можете иметь постоянное состояние, которое использует решатель пути. Если нет, то сложность будет незначительной и, возможно, даже подслушанной, когда эти потоки блокируют изменяющуюся информацию о состоянии игры. Пути могут быть сделаны недействительными от одного кадра к следующему и требуют повторной проверки каждого кадра. Многопоточность может оказаться бессмысленной дополнительной нагрузкой, когда из-за блокировки и синхронизации потоки редко работают параллельно. Это просто возможность.
В качестве альтернативы, вы можете спроектировать свои алгоритмы поиска пути так, чтобы они выполнялись дискретно. По истечении n шагов проверьте количество времени, прошедшее с момента запуска алгоритма. Если он превышает определенное количество времени, алгоритм маршрутизации сохраняет свой прогресс и возвращает. Затем вызывающий код может проверить, завершен ли алгоритм или нет. На следующем кадре возобновите алгоритм пути с того места, где он был. Повторите, пока не решено.
Даже при однопоточном, добровольном подходе к решению путей, если изменения в игровом состоянии влияют на достоверность путей от кадра к кадру, вам придется столкнуться с необходимостью повторной проверки текущих решений для кадра, чтобы каркасное основание.
Использовать частичные решения
При любом из вышеперечисленных подходов вы можете столкнуться с вопросом о единицах, которым приказано пойти куда-нибудь на холостом ходу для нескольких кадров, прежде чем будет иметь полное решение для маршрутизации. Это может быть приемлемым и практически необнаружимым в типичных обстоятельствах. Если это не так, вы можете попытаться использовать неполное решение как есть. Если каждое неполное решение отличается слишком сильно, единицы будут вести себя довольно нерешительно. На практике эта «нерешительность» также может происходить недостаточно часто, чтобы вызывать беспокойство.