add clustered nav coverage task
Document the follow-up refactor from disconnected region surfaces to interest-cluster-based nav coverage windows for runtime pathing.
This commit is contained in:
@@ -65,3 +65,4 @@
|
||||
| TASK-0023 | InProgress | Highest | ai | abysscion | 2d | `docs/tasks/items/TASK-0023.md` | Реализовать runtime NavMesh bake для voxel-чанка и интегрировать обновление навигации при загрузке/изменении чанков. |
|
||||
| TASK-0024 | ToDo | Highest | art | unassigned | 2d | docs/tasks/items/TASK-0024.md | Заменить Minecraft-placeholder арт на легальные ассеты для продакшена и зафиксировать источник/лицензии. |
|
||||
| TASK-0025 | ToDo | Highest | gameplay-core | unassigned | 3d | docs/tasks/items/TASK-0025.md | Перевести player movement на host-authoritative NavMesh pipeline с server-side path planning и shared debug path preview для всех клиентов. |
|
||||
| TASK-0026 | ToDo | Highest | ai | unassigned | 2d | docs/tasks/items/TASK-0026.md | Перевести основной runtime pathing mode на interest-cluster-based coverage windows, чтобы убрать seam-разрывы region-based NavMesh и учитывать multiplayer interest set. |
|
||||
|
||||
@@ -0,0 +1,301 @@
|
||||
---
|
||||
id: TASK-0026
|
||||
title: Перевести runtime NavMesh на interest-cluster-based coverage
|
||||
summary: Заменить основной runtime pathing mode с множества region-based NavMeshData на небольшой набор крупных cluster-based coverage windows, чтобы убрать seam-разрывы и сделать покрытие совместимым с multiplayer interest set.
|
||||
priority: Highest
|
||||
area: ai
|
||||
owner: unassigned
|
||||
created: 2026-04-08
|
||||
updated: 2026-04-08
|
||||
execution_time: 2d
|
||||
depends_on:
|
||||
- TASK-0023
|
||||
canonical_docs:
|
||||
- docs/tasks/Index.md
|
||||
- docs/architecture/mvp-world-authority-navmesh.md
|
||||
- docs/plans/TASK-0023-runtime-navmesh-implementation-plan.md
|
||||
related_files:
|
||||
- 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-0026 - Перевести 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`
|
||||
|
||||
2. **Смена unit of scheduling**
|
||||
|
||||
- было: очередь dirty regions
|
||||
- станет: очередь dirty coverage windows
|
||||
|
||||
3. **Смена unit of readiness**
|
||||
|
||||
- было: неявная region-local готовность
|
||||
- станет: явная coverage readiness по world position
|
||||
|
||||
4. **Смена логики multiplayer coverage**
|
||||
|
||||
- было: первая practical привязка к локальному player interest
|
||||
- станет: `spawn anchors + players + active NPC`
|
||||
|
||||
5. **Уход от 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.
|
||||
Reference in New Issue
Block a user