Навигационные слои: номера и маски
Настроить доступ регионов без ошибки на один бит.
Навигационный слой фильтрует регионы, доступные конкретному запросу пути. Он не создаёт проход, не отключает физическую коллизию и не задаёт габариты персонажа. Для разных размеров персонажей нужна подходящая навигационная геометрия, а не только другая маска.
Номер слоя и маска
В интерфейсе слои нумеруются от 1 до 32. В C# свойство NavigationLayers имеет тип uint; один слой задаётся 1u << (номер - 1).
| Выбранные слои | Маска |
|---|---|
| 1 | 1 |
| 2 | 2 |
| 4 | 8 |
| 1 и 4 | 9 |
| Ни одного | 0 |
Не используйте номер 4 как готовую маску: число 4 выбирает слой 3. Сдвиг 1u << 4 выбирает слой 5. Для старшего слоя нужен беззнаковый 1u; недопустимые номера надо отклонять до сдвига.
Сохраните NavigationLayers.cs в C#-проекте Reckfell 1.0.0:
using System;
public static class NavigationLayers
{
public static uint Bit(int layerNumber)
{
if (layerNumber < 1 || layerNumber > 32)
throw new ArgumentOutOfRangeException(nameof(layerNumber));
return 1u << (layerNumber - 1);
}
public static uint Enable(uint mask, int layerNumber) => mask | Bit(layerNumber);
public static uint Disable(uint mask, int layerNumber) => mask & ~Bit(layerNumber);
public static bool Contains(uint mask, int layerNumber) => (mask & Bit(layerNumber)) != 0;
}Enable(1, 4) возвращает 9; Disable(9, 1) — 8. При изменении существующей маски помощник сохраняет остальные биты. У NavigationRegion2D/3D и NavigationAgent2D/3D также есть SetNavigationLayerValue(номер, включён) — там передаётся номер слоя, а не маска.
Настроить доступ
- Создайте связанные навигационные регионы с уже подготовленными полигонами/мешами. Убедитесь, что они относятся к одной карте и геометрически соединены.
- Назначьте первому региону слой 1, второму — слой 2. Маска региона описывает принадлежность; маска запроса выбирает разрешённые слои.
- Для запроса через оба региона задайте
NavigationLayers = 3. Для доступа только к первому — 1. Условие допуска:(маскаРегиона & маскаЗапроса) != 0. - После изменения регионов дождитесь публикации обновлённой карты. Изменение только маски следующего запроса не требует перестраивать геометрию.
- Проверьте конечную точку результата, а не только наличие точек: при маске 1 маршрут к цели во втором регионе может закончиться у границы первого.
В проверке двух соседних прямоугольников карта с маской 3 соединяет старт и цель. Маска 1 даёт непустой частичный путь, а маска 0 не допускает ни одного региона. Такое поведение подтверждено отдельно для 2D и 3D.
Когда изменения вступают в силу
Изменение маски у запроса применяется при его следующем выполнении. Изменение региона проходит через синхронизацию NavigationServer. Новая карта с MapGetIterationId(map) == 0 ещё не готова к запросу. Ненулевой идентификатор подтверждает наличие опубликованной версии, но не гарантирует, что только что отправленные изменения уже вошли в неё. Не считайте ожидание ровно одного кадра универсальной гарантией готовности.
Для запроса с проверкой обоих концов пути используйте объекты запроса пути.
Если путь неверный
- Маски пересекаются, но прохода нет: проверьте карту, границы и соединения навигационных регионов.
- Персонаж проходит сквозь физическую стену: навигационные слои не заменяют физику; согласуйте навигационный меш с коллизией и движением.
- Получен путь, но не к цели: старт или цель спроецированы на доступную поверхность, либо маршрут частичный.
- Настройка региона изменилась, результат прежний: дождитесь обновлённой версии карты и выполните новый запрос.
Выполнены проверки нумерации 1/4/32, сохранения битов, отказа для 0/33, масок и частичных путей 2D/3D, обновления маски региона 2D после синхронизации. Запекание, интерфейс редактора, NavigationLink, движение агентов и избегание столкновений этим примером не проверяются.