reckfellENGINE

Карты навигации: изоляция и владение

Выбрать карту, перенести регион и освободить свои RID.

На этой странице

Навигационная карта объединяет регионы, связи и данные навигации одного пространства. Это объект NavigationServer с RID, а не Entity, не картинка уровня и не навигационный меш. Соприкасающиеся регионы на разных картах не соединяются.

Использовать карту мира или свою

Внутри дерева Entity2D получает карту мира через GetWorld2D().NavigationMap, Entity3D — через GetWorld3D().NavigationMap. Эта карта принадлежит миру: не освобождайте её вручную. Для региона с отдельной назначенной картой используйте его GetNavigationMap(), иначе можно запросить другой мир.

Отдельная карта нужна для действительно раздельной навигации, например разных наборов проходимой геометрии. Одни только разные права доступа удобнее выражать навигационными слоями. Карты и RID 2D используйте с NavigationServer2D, 3D — с NavigationServer3D.

Создать карту 2D с явным владельцем

Сохраните NavigationMapOwner2D.cs в C#-проекте Reckfell 1.0.0:

C#
using Reckfell;
using System;
using System.Collections.Generic;

public sealed class NavigationMapOwner2D : IDisposable
{
    public Rid Map { get; private set; }
    private readonly List<Rid> _regions = new();
    private readonly List<NavigationPolygon> _polygons = new();

    public NavigationMapOwner2D()
    {
        Map = NavigationServer2D.MapCreate();
        NavigationServer2D.MapSetActive(Map, true);
    }

    public Rid AddRectangle(Rect2 bounds, uint layers = 1)
    {
        if (!Map.IsValid) throw new ObjectDisposedException(nameof(NavigationMapOwner2D));
        if (bounds.Size.X <= 0 || bounds.Size.Y <= 0)
            throw new ArgumentException("Rectangle size must be positive.", nameof(bounds));
        Vector2 a = bounds.Position, b = bounds.End;
        var polygon = new NavigationPolygon
        {
            Vertices = new[] { a, new Vector2(b.X, a.Y), b, new Vector2(a.X, b.Y) }
        };
        polygon.AddPolygon(new[] { 0, 1, 2, 3 });
        Rid region = NavigationServer2D.RegionCreate();
        _regions.Add(region);
        _polygons.Add(polygon);
        NavigationServer2D.RegionSetNavigationPolygon(region, polygon);
        NavigationServer2D.RegionSetNavigationLayers(region, layers);
        NavigationServer2D.RegionSetMap(region, Map);
        return region;
    }

    public void Dispose()
    {
        if (!Map.IsValid) return;
        foreach (Rid region in _regions) NavigationServer2D.FreeRid(region);
        NavigationServer2D.FreeRid(Map);
        Map = default;
        foreach (var polygon in _polygons) polygon.Dispose();
        _regions.Clear(); _polygons.Clear();
    }
}

Создайте экземпляр помощника, затем добавьте прямоугольники через AddRectangle(new Rect2(0, 0, 10, 10)). Координаты задают навигационную поверхность карты; это не видимая графика и не физическая коллизия. Размер должен быть положительным. Помощник содержит карту, регионы и ресурсы полигонов и освобождает их через Dispose().

Возвращённый RID региона можно использовать для настройки, но его владельцем остаётся помощник. Не вызывайте для него FreeRid отдельно и не используйте карту после Dispose(). Если перенесли регион на другую карту, владение не передалось: прежний помощник всё равно освободит этот регион при удалении.

Синхронизация и перенос

RegionSetMap(region, map) назначает карту через очередь сервера. В проверке getter в том же вызове ещё возвращал прежнее значение; после синхронизации — новое. Регион принадлежит только одной карте: перенос убирает его из старого списка и добавляет в новый.

RegionSetMap(region, default) отсоединяет регион, но не освобождает его. Позже его можно назначить снова. После изменения дождитесь публикации геометрии и выполните новый запрос, как описано в работе с сервером.

Что означает Active

MapSetActive(map, true) включает карту в обработку сервером. false не является запретом запросов: в установленной сборке уже опубликованный маршрут продолжает возвращаться и для неактивной карты. Для паузы персонажа остановите игровую логику движения и выдачу новых команд, а не полагайтесь только на этот флаг.

MapGetIterationId(map) == 0 означает отсутствие первой опубликованной версии. Ненулевой ID не подтверждает, что последнее изменение уже обработано. Не приравнивайте создание RID, назначение региона и готовый путь.

Проверка результата

В выполненном примере первая карта содержит прямоугольник x=0–10, вторая — x=10–20. Путь на первой карте не доходит до точки (19, 5), хотя геометрия второй соприкасается с первой. После переноса второго региона на первую карту маршрут доходит до цели.

Если карта пуста, проверьте MapGetRegions, назначение регионов и наличие полигонов. Если путь старый, проверьте синхронизацию. Если возникают ошибки RID, проверьте владельца и момент освобождения. Освобождение одной карты не заменяет освобождение отдельно созданных регионов и связей; помощник делает оба действия явно.

Проверены создание, изоляция карт, перенос/отсоединение региона, неактивная опубликованная карта и освобождение помощника. Автоматическая карта мира сверена с исходниками. Запекание, избегание, интерфейс редактора и изоляция нескольких карт 3D отдельно не проверены.

Документация Reckfell EngineНаверх ↑
БЫСТРЫЙ ПЕРЕХОДНачало работыEntity и иерархияC# & .NET 10Сцены и префабы
Руководства и полный API Reckfell K
reckfellENGINE
RECKFELL ACCOUNT

Вход в аккаунт

Войдите в аккаунт Reckfell.

Один аккаунт для всей платформы Reckfell.