From 1681e44c5e922557bb8128838ef42c1194779efd Mon Sep 17 00:00:00 2001 From: Alexander Borisov Date: Wed, 8 Apr 2026 20:58:30 +0300 Subject: [PATCH] add documentation --- .../Contracts/NavMeshWorldContracts.cs | 54 ++++++++++++++ .../VoxelWorld/Contracts/NavMeshWorldEnums.cs | 20 +++++ .../Contracts/NavMeshWorldMessages.cs | 32 ++++++++ .../Contracts/NavMeshWorldSnapshots.cs | 74 +++++++++++++++++++ .../Runtime/NavCoverageHintService.cs | 18 +++++ .../Runtime/VoxelWorldNavMeshConfig.cs | 3 + .../Runtime/VoxelWorldNavMeshService.cs | 18 +++++ .../VoxelWorld/SceneWorldInterestReader.cs | 9 +++ .../VoxelWorldNavMeshLifetimeScope.cs | 3 + .../VoxelWorldPlayerStreamTargetBinding.cs | 3 + .../VoxelWorld/VoxelWorldSpawnAnchor.cs | 6 ++ 11 files changed, 240 insertions(+) diff --git a/Assets/Features/VoxelWorld/Contracts/NavMeshWorldContracts.cs b/Assets/Features/VoxelWorld/Contracts/NavMeshWorldContracts.cs index c0661a44..dc4e702e 100644 --- a/Assets/Features/VoxelWorld/Contracts/NavMeshWorldContracts.cs +++ b/Assets/Features/VoxelWorld/Contracts/NavMeshWorldContracts.cs @@ -3,34 +3,88 @@ using UnityEngine; namespace InfiniteWorld.VoxelWorld.Contracts { + /// + /// Provides chunk-level nav build inputs without exposing the internal runtime representation of the voxel world. + /// public interface IChunkNavSourceReader { + /// + /// Returns the world-space edge length of one chunk so nav coverage and source collection can reason in chunk units. + /// float ChunkWorldSize { get; } + + /// + /// Copies the coordinates of chunks that currently have usable nav geometry into the provided list. + /// void GetLoadedChunkCoords(List results); + + /// + /// Retrieves the current nav source snapshot for a loaded chunk so sidecar systems can rebuild coverage from stable descriptors. + /// bool TryGetChunkNavSourceSnapshot(Vector2Int coord, out ChunkNavSourceSnapshot snapshot); } + /// + /// Exposes the current gameplay-relevant interest points that should influence world streaming or nav coverage planning. + /// public interface IWorldInterestReader { + /// + /// Increments when the logical set of interest points changes and downstream systems should invalidate cached plans. + /// int InterestVersion { get; } + + /// + /// Appends the currently active interest points into the provided list. + /// void GetInterestPoints(List results); } + /// + /// Exposes the currently built nav coverage so gameplay systems can query whether a world-space area is ready for pathing. + /// public interface INavCoverageReader { + /// + /// Returns whether the supplied world position lies inside ready nav coverage, not merely inside generated terrain. + /// bool IsPositionCovered(Vector3 worldPosition); + + /// + /// Copies the currently active coverage windows so diagnostics and higher-level systems can inspect the coverage topology. + /// void GetCoverageWindows(List results); } + /// + /// Lets callers inject short-lived route hints that bias nav coverage planning toward an upcoming movement corridor. + /// public interface INavCoverageHintRegistry { + /// + /// Registers or refreshes a temporary linear hint for the given owner so coverage can prewarm along a route before pathing starts. + /// void SetLinearHint(int ownerId, Vector3 from, Vector3 to, float priority, float ttlSeconds); + + /// + /// Removes the temporary hint owned by the caller when the route is no longer relevant. + /// void ClearHint(int ownerId); } + /// + /// Exposes the current set of transient nav coverage hints as read-only interest points for the nav coverage scheduler. + /// public interface INavCoverageHintReader { + /// + /// Increments whenever the effective hint set changes so dependent planners can invalidate cached coverage windows. + /// int HintVersion { get; } + + /// + /// Appends the currently active transient hint points into the provided list. + /// void GetHintPoints(List results); } } diff --git a/Assets/Features/VoxelWorld/Contracts/NavMeshWorldEnums.cs b/Assets/Features/VoxelWorld/Contracts/NavMeshWorldEnums.cs index 0f6a3281..2315a288 100644 --- a/Assets/Features/VoxelWorld/Contracts/NavMeshWorldEnums.cs +++ b/Assets/Features/VoxelWorld/Contracts/NavMeshWorldEnums.cs @@ -1,18 +1,38 @@ namespace InfiniteWorld.VoxelWorld.Contracts { + /// + /// Identifies why a point contributes to nav coverage so planners and diagnostics can treat different sources appropriately. + /// public enum WorldInterestKind { + /// Coverage seeded by the current player-controlled actor. PlayerActor = 0, + + /// Coverage seeded by an active NPC that still requires authoritative pathing. ActiveNpc = 1, + + /// Coverage seeded by a spawn location that should be warm before actors start moving. SpawnAnchor = 2, + + /// Coverage seeded by a short-lived route hint that biases planning ahead of movement. TransientNavHint = 3, + + /// Fallback category for future interest sources that do not fit a more specific kind. Other = 4 } + /// + /// Describes where a coverage window currently sits in the nav build lifecycle. + /// public enum NavCoverageState { + /// The window exists conceptually but still needs a fresh build. Pending = 0, + + /// The window is currently rebuilding its runtime NavMesh data. Building = 1, + + /// The window has ready NavMesh data that can answer pathing queries. Ready = 2 } } diff --git a/Assets/Features/VoxelWorld/Contracts/NavMeshWorldMessages.cs b/Assets/Features/VoxelWorld/Contracts/NavMeshWorldMessages.cs index 8c52cd1d..16d9c296 100644 --- a/Assets/Features/VoxelWorld/Contracts/NavMeshWorldMessages.cs +++ b/Assets/Features/VoxelWorld/Contracts/NavMeshWorldMessages.cs @@ -2,6 +2,9 @@ using UnityEngine; namespace InfiniteWorld.VoxelWorld.Contracts { + /// + /// Signals that a chunk now has valid nav geometry and dependent coverage windows should invalidate cached builds. + /// public readonly struct ChunkNavGeometryReadyMessage { public ChunkNavGeometryReadyMessage(Vector2Int coord, int version) @@ -10,10 +13,20 @@ namespace InfiniteWorld.VoxelWorld.Contracts Version = version; } + /// + /// Chunk coordinate whose nav geometry became available. + /// public Vector2Int Coord { get; } + + /// + /// Version of the chunk runtime state associated with this notification. + /// public int Version { get; } } + /// + /// Signals that a chunk's nav geometry is being removed so dependent coverage windows can drop stale build data. + /// public readonly struct ChunkNavGeometryRemovedMessage { public ChunkNavGeometryRemovedMessage(Vector2Int coord, int version) @@ -22,10 +35,20 @@ namespace InfiniteWorld.VoxelWorld.Contracts Version = version; } + /// + /// Chunk coordinate whose nav geometry is no longer available. + /// public Vector2Int Coord { get; } + + /// + /// Last known version of the chunk state before removal. + /// public int Version { get; } } + /// + /// Invalidates consumers that cache the current world interest set. + /// public readonly struct WorldInterestChangedMessage { public WorldInterestChangedMessage(int version) @@ -33,9 +56,15 @@ namespace InfiniteWorld.VoxelWorld.Contracts Version = version; } + /// + /// Monotonic version of the world interest state after the change. + /// public int Version { get; } } + /// + /// Invalidates consumers that cache transient nav coverage hints. + /// public readonly struct NavCoverageHintChangedMessage { public NavCoverageHintChangedMessage(int version) @@ -43,6 +72,9 @@ namespace InfiniteWorld.VoxelWorld.Contracts Version = version; } + /// + /// Monotonic version of the active nav hint state after the change. + /// public int Version { get; } } } diff --git a/Assets/Features/VoxelWorld/Contracts/NavMeshWorldSnapshots.cs b/Assets/Features/VoxelWorld/Contracts/NavMeshWorldSnapshots.cs index 39a564f5..91b4ca0f 100644 --- a/Assets/Features/VoxelWorld/Contracts/NavMeshWorldSnapshots.cs +++ b/Assets/Features/VoxelWorld/Contracts/NavMeshWorldSnapshots.cs @@ -3,6 +3,9 @@ using UnityEngine.AI; namespace InfiniteWorld.VoxelWorld.Contracts { + /// + /// Captures the nav-relevant state of one chunk at a specific version so sidecar systems can rebuild from immutable inputs. + /// public readonly struct ChunkNavSourceSnapshot { public ChunkNavSourceSnapshot(Vector2Int coord, int version, ChunkNavBuildSourceDescriptor[] sources) @@ -12,11 +15,25 @@ namespace InfiniteWorld.VoxelWorld.Contracts Sources = sources; } + /// + /// Chunk coordinate this snapshot was produced for. + /// public Vector2Int Coord { get; } + + /// + /// Version of the chunk runtime state used to generate this snapshot. + /// public int Version { get; } + + /// + /// Stable nav build descriptors derived from the chunk's current geometry. + /// public ChunkNavBuildSourceDescriptor[] Sources { get; } } + /// + /// Describes one build source in a format that can be consumed without direct references to world internals or scene scans. + /// public readonly struct ChunkNavBuildSourceDescriptor { public ChunkNavBuildSourceDescriptor(NavMeshBuildSourceShape shape, Matrix4x4 transform, Vector3 size, Mesh mesh, int area) @@ -28,23 +45,51 @@ namespace InfiniteWorld.VoxelWorld.Contracts Area = area; } + /// + /// Unity NavMesh source shape represented by this descriptor. + /// public NavMeshBuildSourceShape Shape { get; } + + /// + /// World transform used when the descriptor is converted into a runtime build source. + /// public Matrix4x4 Transform { get; } + + /// + /// Source size for primitive shapes such as box-based ground coverage. + /// public Vector3 Size { get; } + + /// + /// Source mesh for mesh-based obstacles or walkable surfaces when applicable. + /// public Mesh Mesh { get; } + + /// + /// Nav area assigned to the resulting build source. + /// public int Area { get; } + /// + /// Creates a compact descriptor for box-based chunk geometry such as ground slabs. + /// public static ChunkNavBuildSourceDescriptor CreateBox(Matrix4x4 transform, Vector3 size, int area = 0) { return new ChunkNavBuildSourceDescriptor(NavMeshBuildSourceShape.Box, transform, size, null, area); } + /// + /// Creates a compact descriptor for mesh-based chunk geometry such as carved terrain or obstacles. + /// public static ChunkNavBuildSourceDescriptor CreateMesh(Matrix4x4 transform, Mesh mesh, int area = 0) { return new ChunkNavBuildSourceDescriptor(NavMeshBuildSourceShape.Mesh, transform, Vector3.zero, mesh, area); } } + /// + /// Represents one gameplay-driven point that should influence nav coverage planning and clustering. + /// public readonly struct WorldInterestPoint { public WorldInterestPoint(Vector3 position, float priority, WorldInterestKind kind) @@ -54,11 +99,25 @@ namespace InfiniteWorld.VoxelWorld.Contracts Kind = kind; } + /// + /// World position the planner should consider when shaping coverage. + /// public Vector3 Position { get; } + + /// + /// Relative weight used to prioritize coverage near more important interest points. + /// public float Priority { get; } + + /// + /// Category of interest so diagnostics can distinguish players, spawn anchors, hints and future AI sources. + /// public WorldInterestKind Kind { get; } } + /// + /// Lightweight read-model snapshot describing one currently managed nav coverage window. + /// public readonly struct NavCoverageWindowSnapshot { public NavCoverageWindowSnapshot(int id, Bounds bounds, NavCoverageState state, int interestCount) @@ -69,9 +128,24 @@ namespace InfiniteWorld.VoxelWorld.Contracts InterestCount = interestCount; } + /// + /// Stable runtime identifier of the coverage window. + /// public int Id { get; } + + /// + /// World-space bounds the window currently covers for pathing readiness. + /// public Bounds Bounds { get; } + + /// + /// Current lifecycle state of the window in the build scheduler. + /// public NavCoverageState State { get; } + + /// + /// Number of interest points currently collapsed into this window. + /// public int InterestCount { get; } } } diff --git a/Assets/Features/VoxelWorldNavMesh/Runtime/NavCoverageHintService.cs b/Assets/Features/VoxelWorldNavMesh/Runtime/NavCoverageHintService.cs index 0662ede7..642af643 100644 --- a/Assets/Features/VoxelWorldNavMesh/Runtime/NavCoverageHintService.cs +++ b/Assets/Features/VoxelWorldNavMesh/Runtime/NavCoverageHintService.cs @@ -7,6 +7,9 @@ using VContainer.Unity; namespace InfiniteWorld.VoxelWorld.NavMesh { + /// + /// Stores short-lived route hints and expands them into interest points so nav coverage can prewarm ahead of movement. + /// public sealed class NavCoverageHintService : ITickable, INavCoverageHintRegistry, INavCoverageHintReader { private readonly IChunkNavSourceReader chunkNavSourceReader; @@ -27,8 +30,14 @@ namespace InfiniteWorld.VoxelWorld.NavMesh this.hintChangedPublisher = hintChangedPublisher; } + /// + /// Increments whenever the effective set of active hints changes and cached coverage planning should be invalidated. + /// public int HintVersion => hintVersion; + /// + /// Expires hints whose time-to-live has elapsed so stale route bias does not keep shaping coverage forever. + /// public void Tick() { if (hints.Count == 0) @@ -61,6 +70,9 @@ namespace InfiniteWorld.VoxelWorld.NavMesh NotifyHintsChanged(); } + /// + /// Registers or refreshes a temporary linear corridor for one owner so coverage can be biased along an upcoming route. + /// public void SetLinearHint(int ownerId, Vector3 from, Vector3 to, float priority, float ttlSeconds) { if (ownerId == 0) @@ -74,6 +86,9 @@ namespace InfiniteWorld.VoxelWorld.NavMesh NotifyHintsChanged(); } + /// + /// Removes a previously registered route hint once the owner no longer needs prewarmed coverage. + /// public void ClearHint(int ownerId) { if (!hints.Remove(ownerId)) @@ -84,6 +99,9 @@ namespace InfiniteWorld.VoxelWorld.NavMesh NotifyHintsChanged(); } + /// + /// Appends the currently active hint points so the main coverage scheduler can treat them like supplemental interest. + /// public void GetHintPoints(List results) { if (results == null) diff --git a/Assets/Features/VoxelWorldNavMesh/Runtime/VoxelWorldNavMeshConfig.cs b/Assets/Features/VoxelWorldNavMesh/Runtime/VoxelWorldNavMeshConfig.cs index a81fd35a..cfebcf2d 100644 --- a/Assets/Features/VoxelWorldNavMesh/Runtime/VoxelWorldNavMeshConfig.cs +++ b/Assets/Features/VoxelWorldNavMesh/Runtime/VoxelWorldNavMeshConfig.cs @@ -4,6 +4,9 @@ using UnityEngine; namespace InfiniteWorld.VoxelWorld.NavMesh { [Serializable] + /// + /// Inspector-friendly tuning parameters that bound how clustered nav coverage is shaped and rebuilt at runtime. + /// public sealed class VoxelWorldNavMeshConfig { [Min(0)] public int agentTypeId; diff --git a/Assets/Features/VoxelWorldNavMesh/Runtime/VoxelWorldNavMeshService.cs b/Assets/Features/VoxelWorldNavMesh/Runtime/VoxelWorldNavMeshService.cs index e63975df..fc95f544 100644 --- a/Assets/Features/VoxelWorldNavMesh/Runtime/VoxelWorldNavMeshService.cs +++ b/Assets/Features/VoxelWorldNavMesh/Runtime/VoxelWorldNavMeshService.cs @@ -10,6 +10,9 @@ using UnityNavMeshBuilder = UnityEngine.AI.NavMeshBuilder; namespace InfiniteWorld.VoxelWorld.NavMesh { + /// + /// Coordinates clustered runtime NavMesh coverage over the voxel world by rebuilding a bounded set of windows around active interest. + /// public sealed class VoxelWorldNavMeshService : IStartable, ITickable, IDisposable, INavCoverageReader { private readonly IChunkNavSourceReader chunkNavSourceReader; @@ -54,6 +57,9 @@ namespace InfiniteWorld.VoxelWorld.NavMesh this.config = config ?? new VoxelWorldNavMeshConfig(); } + /// + /// Subscribes to world invalidation and primes the initial set of coverage windows for the current interest snapshot. + /// public void Start() { subscriptions.Add(chunkReadySubscriber.Subscribe(OnChunkNavGeometryReady)); @@ -66,6 +72,9 @@ namespace InfiniteWorld.VoxelWorld.NavMesh MarkAllCoverageWindowsDirty(); } + /// + /// Advances the clustered coverage scheduler, refreshing interest and starting bounded asynchronous builds when needed. + /// public void Tick() { RefreshInterestPoints(); @@ -92,6 +101,9 @@ namespace InfiniteWorld.VoxelWorld.NavMesh } } + /// + /// Returns whether the supplied world position is inside a ready coverage window and can be treated as nav-ready. + /// public bool IsPositionCovered(Vector3 worldPosition) { foreach (KeyValuePair pair in coverageWindows) @@ -106,6 +118,9 @@ namespace InfiniteWorld.VoxelWorld.NavMesh return false; } + /// + /// Copies the current runtime coverage windows for diagnostics, readiness checks and higher-level planning. + /// public void GetCoverageWindows(List results) { if (results == null) @@ -120,6 +135,9 @@ namespace InfiniteWorld.VoxelWorld.NavMesh } } + /// + /// Releases subscriptions and runtime NavMesh data owned by the service. + /// public void Dispose() { for (int i = 0; i < subscriptions.Count; i++) diff --git a/Assets/Scripts/VoxelWorld/SceneWorldInterestReader.cs b/Assets/Scripts/VoxelWorld/SceneWorldInterestReader.cs index 1b3b67e7..6b480824 100644 --- a/Assets/Scripts/VoxelWorld/SceneWorldInterestReader.cs +++ b/Assets/Scripts/VoxelWorld/SceneWorldInterestReader.cs @@ -5,6 +5,9 @@ using UnityEngine; namespace VoxelWorldScene { + /// + /// Combines the world generator's current stream target with scene spawn anchors into one interest feed for nav coverage. + /// public sealed class SceneWorldInterestReader : IWorldInterestReader { private readonly VoxelWorldGenerator worldGenerator; @@ -16,8 +19,14 @@ namespace VoxelWorldScene this.worldGenerator = worldGenerator; } + /// + /// Mirrors the generator's interest version so downstream systems can invalidate cached plans when scene interest changes. + /// public int InterestVersion => worldGenerator != null ? worldGenerator.InterestVersion : 0; + /// + /// Appends both dynamic actor interest and static spawn-anchor interest into the supplied list. + /// public void GetInterestPoints(List results) { if (results == null) diff --git a/Assets/Scripts/VoxelWorld/VoxelWorldNavMeshLifetimeScope.cs b/Assets/Scripts/VoxelWorld/VoxelWorldNavMeshLifetimeScope.cs index 425f0be3..333264b7 100644 --- a/Assets/Scripts/VoxelWorld/VoxelWorldNavMeshLifetimeScope.cs +++ b/Assets/Scripts/VoxelWorld/VoxelWorldNavMeshLifetimeScope.cs @@ -10,6 +10,9 @@ namespace VoxelWorldScene { [DisallowMultipleComponent] [RequireComponent(typeof(VoxelWorldGenerator))] + /// + /// Scene-level composition root that wires the voxel world, nav coverage services and interest readers into one runtime module. + /// public sealed class VoxelWorldNavMeshLifetimeScope : LifetimeScope { [SerializeField] private bool enableRuntimeNavMesh = true; diff --git a/Assets/Scripts/VoxelWorld/VoxelWorldPlayerStreamTargetBinding.cs b/Assets/Scripts/VoxelWorld/VoxelWorldPlayerStreamTargetBinding.cs index 15faee3e..b612351e 100644 --- a/Assets/Scripts/VoxelWorld/VoxelWorldPlayerStreamTargetBinding.cs +++ b/Assets/Scripts/VoxelWorld/VoxelWorldPlayerStreamTargetBinding.cs @@ -6,6 +6,9 @@ namespace VoxelWorldScene { [DisallowMultipleComponent] [RequireComponent(typeof(VoxelWorldGenerator))] + /// + /// Keeps the voxel world streaming target aligned with the local player when available, or a spawn anchor as a safe fallback. + /// public sealed class VoxelWorldPlayerStreamTargetBinding : MonoBehaviour { [SerializeField] private VoxelWorldGenerator worldGenerator; diff --git a/Assets/Scripts/VoxelWorld/VoxelWorldSpawnAnchor.cs b/Assets/Scripts/VoxelWorld/VoxelWorldSpawnAnchor.cs index 733e85eb..31235931 100644 --- a/Assets/Scripts/VoxelWorld/VoxelWorldSpawnAnchor.cs +++ b/Assets/Scripts/VoxelWorld/VoxelWorldSpawnAnchor.cs @@ -3,10 +3,16 @@ using UnityEngine; namespace VoxelWorldScene { [DisallowMultipleComponent] + /// + /// Marks a scene transform that should contribute interest before players move so spawn areas can be prewarmed for nav coverage. + /// public sealed class VoxelWorldSpawnAnchor : MonoBehaviour { [SerializeField, Min(0.01f)] private float priority = 2f; + /// + /// Relative importance of this anchor when coverage planning competes between multiple spawn-related interests. + /// public float Priority => priority; } }