using System.Collections.Generic; using InfiniteWorld.VoxelWorld.Contracts; using UnityEngine; using UnityEngine.AI; namespace InfiniteWorld.VoxelWorld.NavMesh { internal static class NavBuildSourceCollector { public static bool CollectBuildSources( IChunkNavSourceReader chunkNavSourceReader, Bounds coverageBounds, List loadedChunkCoords, List results) { loadedChunkCoords.Clear(); chunkNavSourceReader.GetLoadedChunkCoords(loadedChunkCoords); bool hasSources = false; for (int i = 0; i < loadedChunkCoords.Count; i++) { Vector2Int chunkCoord = loadedChunkCoords[i]; if (!NavMeshBoundsUtility.IntersectsXZ(GetChunkWorldBounds(chunkNavSourceReader, chunkCoord), coverageBounds)) { continue; } if (!chunkNavSourceReader.TryGetChunkNavSourceSnapshot(chunkCoord, out ChunkNavSourceSnapshot snapshot) || snapshot.Sources == null || snapshot.Sources.Length == 0) { continue; } hasSources = true; AppendBuildSources(snapshot.Sources, results); } return hasSources; } public static Bounds GetChunkWorldBounds(IChunkNavSourceReader chunkNavSourceReader, Vector2Int chunkCoord) { float chunkSize = Mathf.Max(1f, chunkNavSourceReader.ChunkWorldSize); Vector3 min = new Vector3(chunkCoord.x * chunkSize, -500f, chunkCoord.y * chunkSize); Vector3 size = new Vector3(chunkSize, 1000f, chunkSize); return new Bounds(min + new Vector3(chunkSize * 0.5f, 0f, chunkSize * 0.5f), size); } public static Bounds ExpandCoverageBounds(IChunkNavSourceReader chunkNavSourceReader, Bounds bounds, int chunkMargin) { return ExpandChunkBounds(chunkNavSourceReader, bounds, chunkMargin); } public static Bounds ExpandChunkBounds(IChunkNavSourceReader chunkNavSourceReader, Bounds bounds, int chunkMargin) { float chunkSize = Mathf.Max(1f, chunkNavSourceReader.ChunkWorldSize); float horizontalPadding = chunkMargin * chunkSize; bounds.Expand(new Vector3(horizontalPadding * 2f, 0f, horizontalPadding * 2f)); return bounds; } private static void AppendBuildSources(ChunkNavBuildSourceDescriptor[] descriptors, List results) { for (int i = 0; i < descriptors.Length; i++) { ChunkNavBuildSourceDescriptor descriptor = descriptors[i]; if (descriptor.Shape == NavMeshBuildSourceShape.Mesh && descriptor.Mesh == null) { continue; } NavMeshBuildSource source = new NavMeshBuildSource { area = descriptor.Area, shape = descriptor.Shape, transform = descriptor.Transform, size = descriptor.Size, sourceObject = descriptor.Shape == NavMeshBuildSourceShape.Mesh ? descriptor.Mesh : null }; results.Add(source); } } } }