using System.Collections.Generic; using Cysharp.Threading.Tasks; using Unity.Mathematics; using UnityEngine; namespace DanieleMarotta.RiversongCodeShowcase { public class TerrainGeneratorOperation : IWorldGeneratorOperation { [InjectService] private GameConfig _config; [InjectService] private IScene _scene; [InjectService] private WorldRenderingState _renderingState; public async UniTask Execute(World world) { var generators = new List { new TerrainChunkMeshGenerator(world, _config), new GrassChunkMeshGenerator(world, _config), new CropsChunkMeshGenerator(world, _config) }; var chunkSize = _config.WorldGen.ChunkSize; var horizontalResolution = Mathf.CeilToInt((float)world.Size.x / chunkSize); var verticalResolution = Mathf.CeilToInt((float)world.Size.y / chunkSize); for (var x = 0; x < horizontalResolution; x++) for (var y = 0; y < verticalResolution; y++) { var chunk = CreateChunk(x, y); foreach (var generator in generators) generator.InitializeChunk(chunk); _renderingState.AddTerrainChunk(chunk); } await UniTask.NextFrame(); var batch = new List(_config.WorldGen.ChunkGenerationBatchCount); var count = 0; while (count < _renderingState.TerrainChunks.Count) { batch.Clear(); for (var i = 0; i < _config.WorldGen.ChunkGenerationBatchCount; i++) { batch.Add(_renderingState.TerrainChunks[count]); if (++count >= _renderingState.TerrainChunks.Count) break; } foreach (var generator in generators) generator.BeginGeneratingChunks(batch); foreach (var generator in generators) await generator.Wait(); foreach (var generator in generators) { generator.EndGeneratingChunks(); await UniTask.NextFrame(); } } } private TerrainChunk CreateChunk(int x, int y) { var chunk = new TerrainChunk { Coords = new int2(x, y), Root = new GameObject($"Chunk_{x}_{y}") }; chunk.Root.transform.SetParent(_scene.SceneFolders.TerrainChunks); chunk.GrassLODs = new TerrainChunk.RenderData[_config.Terrain.GrassLODs.Length]; chunk.CropsLODs = new TerrainChunk.RenderData[_config.Terrain.CropsLODs.Length]; return chunk; } } }