Files
TheDeclineOfWarriors/docs/tasks/items/TASK-0028.md
T
2026-04-08 20:41:40 +03:00

15 KiB
Raw Blame History

id, title, summary, priority, area, owner, created, updated, execution_time, depends_on, canonical_docs, related_files
id title summary priority area owner created updated execution_time depends_on canonical_docs related_files
TASK-0028 Перевести runtime NavMesh на interest-cluster-based coverage Заменить основной runtime pathing mode с множества region-based NavMeshData на небольшой набор крупных cluster-based coverage windows, чтобы убрать seam-разрывы и сделать покрытие совместимым с multiplayer interest set. Highest ai unassigned 2026-04-08 2026-04-08 2d
TASK-0023
docs/tasks/Index.md
docs/architecture/mvp-world-authority-navmesh.md
docs/plans/TASK-0023-runtime-navmesh-implementation-plan.md
Assets/Features/VoxelWorldNavMesh/Runtime/VoxelWorldNavMeshService.cs
Assets/Features/VoxelWorldNavMesh/Runtime/VoxelWorldNavMeshConfig.cs
Assets/Features/VoxelWorld/Contracts/NavMeshWorldContracts.cs
Assets/Features/VoxelWorld/Runtime/VoxelWorldGenerator.cs

TASK-0028 - Перевести runtime NavMesh на interest-cluster-based coverage

Status

Статус задачи ведется в docs/tasks/Index.md и является каноническим там.

Why

Текущая region-based runtime NavMesh схема подтверждает локальную работоспособность build pipeline, но уже показала архитектурно важную проблему: pathfinding между соседними зонами покрытия дает PathPartial, даже когда destination сам лежит на NavMesh.

Это означает, что текущий основной runtime pathing mode опирается на набор разрозненных nav islands и не гарантирует непрерывный navigation graph между активными зонами симуляции.

Для multiplayer host-authoritative pathing этого недостаточно. Хосту нужен не просто локально построенный NavMesh, а непрерывное coverage в активной области симуляции без систематических seam-разрывов на границах мелких регионов.

Expected Outcome

  • Основной runtime pathing mode больше не строится как множество мелких независимых NavMeshData по nav regions.
  • Вместо этого используется небольшой набор крупных coverage windows, каждый из которых покрывает interest cluster.
  • Внутри активной области симуляции pathfinding не ломается на границах бывших nav regions.
  • Coverage учитывает не только одного игрока, а multiplayer interest set: spawn anchors + players + active NPC.
  • Модуль остается sidecar-решением поверх VoxelWorld, без hardwiring внутрь VoxelWorldGenerator.

Current Context

Сейчас runtime NavMesh уже вынесен в sidecar-модуль и строится локально на каждом peer:

  • VoxelWorldGenerator отдает nav sources через contracts;
  • VoxelWorldNavMeshService собирает sources из chunk snapshots;
  • build идет локально и не реплицируется по сети;
  • authority gameplay сохраняется у хоста.

Однако unit of build и unit of scheduling пока выбраны неудачно как основной pathing mode:

  • много мелких NavMeshData по region-based сетке;
  • pathfinding между region surfaces может распадаться на отдельные islands;
  • visual continuity overlay не гарантирует graph connectivity для NavMesh.CalculatePath / NavMeshAgent.

Source Of Truth

  • docs/architecture/mvp-world-authority-navmesh.md
  • docs/plans/TASK-0023-runtime-navmesh-implementation-plan.md
  • фактическая реализация VoxelWorldNavMeshService
  • подтвержденные smoke-test результаты с PathPartial на границах region coverage

Read First

  • Assets/Features/VoxelWorldNavMesh/Runtime/VoxelWorldNavMeshService.cs
  • Assets/Features/VoxelWorldNavMesh/Runtime/VoxelWorldNavMeshConfig.cs
  • Assets/Features/VoxelWorld/Contracts/NavMeshWorldContracts.cs
  • Assets/Features/VoxelWorld/Runtime/VoxelWorldGenerator.cs
  • docs/architecture/mvp-world-authority-navmesh.md

Fixed Decisions

1. NavMesh remains local-build sidecar state

NavMesh по-прежнему:

  • строится локально на каждом peer;
  • не реплицируется как data blob;
  • остается derived cache от world state;
  • не является authoritative network state.

2. Chunk stays source/invalidation unit, not build unit

Chunk остается:

  • источником nav build sources;
  • unit of invalidation для world lifecycle;
  • источником dirty notifications.

Chunk не должен оставаться каноническим unit of nav coverage build.

3. Coverage window is built from interest clusters, not from one player and not from camera

Нельзя строить канонический runtime pathing вокруг:

  • Camera.main;
  • только одного tracked player;
  • presentation-level сущности.

Coverage должен строиться вокруг interest clusters, формируемых из:

  • spawn anchors;
  • players;
  • active NPC.

4. One player does not imply one dedicated volume

Нельзя закреплять правило один игрок = один volume.

Правильная модель:

  • один spatially coherent interest cluster = один coverage window;
  • близкие игроки и NPC должны merge'иться в один cluster;
  • число active windows должно быть bounded.

5. Scene scan through NavMeshSurface sample is not the canonical integration model

Подход из sample NavMeshSurfaceVolumeUpdater полезен как диагностическая подсказка, но не должен становиться буквальной production integration model.

Канонический путь для проекта:

  • bounds уровня sliding coverage window;
  • build sources из IChunkNavSourceReader / world contracts;
  • DI + typed MessagePipe + reader contracts.

6. Spawn readiness must become first-class

Покрытие должно учитывать spawn anchors до player movement activation. Нельзя полагаться на то, что NavMesh magically появится только после того, как actor уже стал единственной точкой интереса.

Scope In

  • замена основного runtime pathing mode с region-based surfaces на cluster-based coverage windows;
  • новый scheduler по coverage windows;
  • cluster builder для players + active NPC + spawn anchors;
  • build source collection по bounds окна, а не по одному nav region;
  • read-model для current nav coverage state;
  • explicit coverage readiness для spawn / first path command / AI activation;
  • bounded merge policy для близких interest points;
  • debug visibility coverage windows.

Scope Out

  • изменение authority model NPC/AI;
  • репликация NavMesh;
  • полноценная crowd avoidance система;
  • multi-agent taxonomy beyond current single-agent MVP;
  • player host-authoritative navigation system как отдельная feature-задача;
  • большой рефактор world feature вне необходимого nav contracts surface.

Required Architecture

New canonical unit: interest cluster

Нужна новая внутренняя модель coverage:

  • WorldInterestPoint остается atomic input;
  • NavInterestCluster становится unit of grouping;
  • NavCoverageWindow становится unit of build and readiness.

Минимальная ответственность cluster builder:

  • собрать текущий interest set;
  • spatially merge близкие точки интереса;
  • стабилизировать cluster ids между обновлениями;
  • строить quantized window bounds с margin.

Coverage window replaces region as primary build unit

Coverage window должен хранить:

  • cluster id;
  • current bounds;
  • NavMeshData / NavMeshDataInstance;
  • dirty/building/ready state;
  • список covered chunks или equivalent cached source membership.

Source collection remains contract-driven

Build sources должны собираться:

  • не через scene scan;
  • не через direct references на private world internals;
  • а через IChunkNavSourceReader и chunk nav source snapshots.

Chunk используется как source/invalidation unit, но не как primary coverage unit.

Coverage state must be queryable

Нужен reader contract уровня:

  • INavCoverageReader

Минимальная ответственность:

  • IsPositionCovered(Vector3 worldPosition);
  • возможность получить current active coverage windows;
  • возможность проверить readiness для spawn/path activation.

Scheduler must be bounded and quantized

Нельзя rebuild'ить coverage window на каждый микрошаг игрока.

Нужны:

  • quantized movement threshold;
  • bounded number of active windows;
  • bounded builds per frame;
  • rebuild только при существенном смещении cluster bounds, изменении cluster composition или chunk invalidation внутри covered bounds.

Suggested Runtime Structure

New or refactored runtime types

  • NavInterestClusterBuilder
  • NavCoverageWindowRuntime
  • NavCoverageWindowSnapshot
  • NavBuildSourceCollector
  • INavCoverageReader
  • VoxelWorldClusteredNavMeshService или equivalent refactor текущего VoxelWorldNavMeshService

Config changes

Текущий config должен сместиться от region-centric параметров к cluster/window-centric:

  • clusterMergeDistance
  • clusterBoundsPadding
  • clusterRebuildQuantization
  • maxActiveCoverageWindows
  • chunkCollectionMarginInChunks
  • maxBuildsPerFrame

Если старые region-centric поля остаются временно ради миграции, они не должны продолжать определять основной runtime pathing mode.

Main Highlights Of Changes

  1. Смена unit of build
  • было: nav region
  • станет: interest cluster coverage window
  1. Смена unit of scheduling
  • было: очередь dirty regions
  • станет: очередь dirty coverage windows
  1. Смена unit of readiness
  • было: неявная region-local готовность
  • станет: явная coverage readiness по world position
  1. Смена логики multiplayer coverage
  • было: первая practical привязка к локальному player interest
  • станет: spawn anchors + players + active NPC
  1. Уход от seam-first topology
  • было: pathing через сеть мелких surfaces с риском disconnected islands
  • станет: меньшее число более цельных coverage windows

Acceptance Criteria

  • Основной runtime pathing mode больше не опирается на множество мелких region-based NavMeshData как на primary navigation graph.
  • Destination на NavMesh в соседней активной области больше не приводит систематически к PathPartial только из-за seam между бывшими nav regions.
  • Coverage формируется по interest clusters, а не по одному tracked player и не по Camera.main.
  • Spawn anchors участвуют в initial nav coverage.
  • Нужное coverage state можно query'ить через reader contract.
  • Sidecar-модуль остается отключаемым без переписывания VoxelWorld core.
  • Build pipeline остается bounded и пригодным для WebGL-host бюджета.

Verification

  • ручной тест: pathfinding между соседними активными областями больше не обрывается на границе бывших region surfaces;
  • ручной тест: при удалении игроков друг от друга coverage windows корректно split/merge'ятся по кластерам;
  • ручной тест: spawn area получает nav coverage до first path command;
  • ручной тест: pathfinding внутри cluster window и между близкими covered areas дает PathComplete, где раньше получался PathPartial из-за seam;
  • debug visualization coverage windows подтверждает ожидаемую cluster topology.

Risks / Open Questions

  • Один большой coverage window может снять seam-problem, но оказаться слишком тяжелым для host CPU budget; поэтому bounded cluster windows важнее, чем просто "один volume на весь мир".
  • Слишком агрессивное merge policy может раздуть rebuild cost; слишком слабое merge policy вернет seam-problem в другой форме.
  • Нужна аккуратная стратегия стабильных cluster ids, иначе scheduler и debug tooling будут шумными.
  • Возможно понадобится временный dual-mode rollout: region mode как fallback, clustered mode как новый primary pathing mode до подтверждения стабильности.

Human Decisions Needed

  • none currently

Decision Log

  • 2026-04-08 - подзадача выделена после smoke-test'а runtime NavMesh, который подтвердил локальную работоспособность build pipeline, но выявил PathPartial на границах region-based coverage.

Handoff Notes

Эта задача не отменяет базовые решения TASK-0023, а уточняет основной runtime pathing mode. Не возвращать интеграцию к Camera.main или scene-scan-driven sample как к канонической архитектуре. Sample NavMeshSurfaceVolumeUpdater использовать только как источник идеи sliding coverage, но не как буквальную production integration model.