Преобразование сетки в график для навигации

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

Всем привет!

Я работаю над многопользовательской игрой, которая требует, чтобы сервер мог выполнять поиск пути для объектов, контролируемых сервером. Сервер представляет собой прямое приложение C#, а клиент использует игровой движок Unity. Использование Unity на сервере не вариант. Кроме того, я хотел бы полностью избежать нативных библиотек.

Я уже изучил Detour для поиска пути, и хотя у них есть переносы на C#, я бы предпочел собственную реализацию фактического бита поиска пути; поскольку процесс достаточно прост, и я хотел бы, чтобы он был адаптирован к моим потребностям, чтобы он хорошо сочетался с существующими компонентами на сервере.

В Unity встроена поддержка Recast/Detour. Это хорошо, так как я могу использовать Recast в Unity для создания навигационной сетки; затем используйте его на сервере, используя мой собственный поиск пути. Проблема в том, что я не могу найти правильный способ создания графика на основе сетки, созданной Unity/Recast.

Что мне нужно сделать, так это создать граф в памяти, где каждый узел представляет собой треугольник в сетке, а каждое ребро графа соединяет два треугольника, которые примыкают друг к другу.

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

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

Unity Navmesh

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

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

if (sharedVertexCount == 2)
    connectPolygons()
else if (sharedVertexCount == 1)
    Vector3[] parallelLine = findParallelLineSharedByBothPolygons()
    if (parallelLine != null)
        Vector3 otherPoint = getUnsharedPointInLine(parallelLine)
        if (isPointInLine(parallelLine, otherPoint))
            connectPolygons()

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

В любом случае должно быть более простое решение; тем не менее, я не нашел в Интернете ничего, что указывало бы мне в этом направлении... вот почему я спрашиваю вас, хорошие ребята, могу ли я что-нибудь сделать, чтобы эффективно превратить сгенерированную навигационную сетку в граф связанных полигонов. Либо помощь с моей реализацией isPointInLine, либо указание мне в направлении более разумного алгоритма будут оценены без слов.


person LittlePip    schedule 08.02.2014    source источник


Ответы (2)


Когда дело доходит до поиска пути, большинство методов предлагают заранее созданную структуру данных, предназначенную для навигации, с которой легче работать (если только ваша графическая структура данных не достаточно проста — здесь это не так).

Я предлагаю вам несколько решений:

  • Навигационная система на основе вокселей: реализация воксельной системы с трехмерным массивом логических значений (не может/не проходит) и применение к ней алгоритма A Star или D Star.

  • Знайте векторы пути, известные ИИ, через которые он может пройти.

  • Слияние двух систем (основные пути используют известные векторы пути, в то время как меши подписывают воксель, который пересекается с ложным. - Вероятно, это решение, которое вы ищете.

person Tamir Vered    schedule 08.02.2014
comment
Что ж, я определенно мог бы отказаться от использования Recast в Unity и написать свой собственный автоматический генератор навигационной сетки; но с треугольниками, экспортированными из навигационной сетки Unity, я невероятно близок к тому, чтобы работающая реализация использовала их в качестве входных данных для моей системы поиска пути. По сути, вы предполагаете, что этот подход не стоит проблем? - person LittlePip; 08.02.2014
comment
Этот метод герметичен, для большинства приложений (игры и т.д.) вам не нужно герметичное решение, вам нужно рабочее простое ремонтопригодное решение. А я разработчик программной инфраструктуры, люблю герметичные решения, лол... - person Tamir Vered; 08.02.2014
comment
D* устарел, если он вам действительно нужен, вы должны использовать вместо него D*-Lite. Однако даже D*-Lite довольно редко встречается в играх, потому что он намного сложнее, чем A*. Подробнее см. здесь. - person BlueRaja - Danny Pflughoeft; 08.02.2014

Если я правильно понял вашу проблему, алгоритмы планирования пути на основе графика видимости могут помочь:

Подсказка состоит в том, чтобы извлечь граф из существующей карты полигонов, в которой узлы связаны, когда они напрямую доступны друг другу. Получившийся так называемый график видимости (см. https://en.wikipedia.org/wiki/Visibility_graph), затем можно использовать для навигации с помощью обычных алгоритмов кратчайшего пути (https://en.wikipedia.org/wiki/Shorttest_path_problem).

Существует немало алгоритмов для эффективного извлечения графа видимости для планирования пути. Вот несколько связанных ссылок:

Тезис, описывающий общая процедура и несколько настроек в главе 4.4

Мой пакет Python для планирования пути на основе видимости

Библиотека C++ с открытым исходным кодом для 2D-алгоритмов видимости с плавающей запятой, планирования пути

Документ об алгоритме Ли

реализация алгоритма Ли на C

person MrMinimal64    schedule 07.10.2018