NavigationServer: объекты, очередь и готовность
Не путать назначенные свойства с опубликованной навигацией.
NavigationServer2D и NavigationServer3D управляют картами, регионами, связями и запросами своей размерности. Entity NavigationRegion, NavigationLink и NavigationAgent используют сервер внутри. Прямой API нужен, когда вы сами управляете процедурной геометрией или жизненным циклом навигационных объектов; он не делает движение персонажа автоматически.
Что выбрать
| Задача | Подход |
|---|---|
| Расставить регионы и связи в редакторе | Используйте соответствующие Entity и их свойства. |
| Создать процедурные поверхности | Создайте карту/регионы через сервер с явным владельцем RID. |
| Получить только точки маршрута | MapGetPath; пример прямого пути. |
| Нужны фильтры, метаданные и ограничения | QueryPath; объекты запроса. |
RID и владение
RID идентифицирует объект сервера; это не ID Entity и не сохраняемый путь к ресурсу. MapCreate создаёт карту, RegionCreate — регион. В запрос передаётся RID карты, в RegionSetMap — сначала регион, затем карта. Не меняйте местами RID разных типов и не передавайте их другому серверу размерности.
Обычная навигационная Entity управляет своим серверным объектом. При прямом создании владельцем становитесь вы: сохраните RID, назначьте карту, добавьте данные, затем освободите через FreeRid. Завершённый пример такого владения — помощник карты 2D.
Почему Set и Get в одном кадре различаются
Многие изменяющие вызовы ставят команду в очередь. Getter может читать ещё прежнее состояние сервера; getter Entity может читать уже присвоенное локальное свойство. Создание объекта, обработка команды и публикация новой геометрии — разные события.
Проверенный порядок для процедурного уровня:
- Создайте карту и включите обработку.
- Создайте регионы, задайте полигоны/меши, слои и карту.
- Дождитесь опубликованной навигации. При нулевом
MapGetIterationIdзапрос ещё рано выполнять. - Выполните запрос и проверьте его точки и концы.
- При переносе или изменении геометрии дождитесь новой публикации и запросите путь снова.
Не считайте один await PhysicsFrame универсальной гарантией готовности: асинхронная сборка региона и карты может занять несколько шагов. В проверочном проекте используется ограниченное ожидание между изменениями; это не норматив задержки для любой игры. Ненулевой iteration ID подтверждает опубликованную версию, но не свежесть всех отправленных команд.
MapForceUpdate существует для принудительной синхронизации. Не заменяйте им обычный цикл каждый кадр и не обещайте, что один вызов завершит любую асинхронную работу. Пример здесь не проверяет такой гарантии.
Запрос, движение и избегание
Точки пути описывают маршрут. Игра отдельно выбирает следующую точку, вычисляет скорость, выполняет движение с коллизией и обрабатывает переходы через связи. Избегание агентов — отдельный механизм; callback расчёта скорости не равен результату MapGetPath. Не перезаписывайте игровую позицию массивом точек, ожидая физически корректного движения.
Очередь серверных команд не делает произвольные операции с Entity безопасными из фонового потока. Потоковую модель конкретного API проверяйте отдельно; данный пример выполняется в обычном цикле движка.
Выполнены проверки очереди назначения карты, последующего чтения, переноса региона, запросов и явного освобождения объектов. Многопоточные вызовы, избегание/callback, гарантии MapForceUpdate и движение не проверены этим набором.