/// <summary> /// Generates block types with hp and hp level. /// Chunks and their objects (if first run = true). /// And calculates faces. /// </summary> public IEnumerator CreateWorld(bool firstRun, Action callback) { _terrainGenerator.Initialize(Settings); _meshGenerator.Initialize(Settings); _stopwatch.Restart(); ResetProgressBarVariables(); ProgressDescription = "Initialization..."; Status = WorldGeneratorStatus.NotReady; Blocks = new BlockData[Settings.WorldSizeX * CHUNK_SIZE, WORLD_SIZE_Y *CHUNK_SIZE, Settings.WorldSizeZ *CHUNK_SIZE]; AlreadyGenerated += _progressStep; yield return(null); if (Settings.ComputingAcceleration == ComputingAcceleration.UnityJobSystem) { ProgressDescription = "Calculating heights..."; var heights = _terrainGenerator.CalculateHeightsJobSystem(); AlreadyGenerated += _progressStep; yield return(null); ProgressDescription = "Calculating block types..."; var types = _terrainGenerator.CalculateBlockTypes(heights); AlreadyGenerated += _progressStep; yield return(null); ProgressDescription = "Job output deflattenization..."; DeflattenizeOutput(ref types); AlreadyGenerated += _progressStep; yield return(null); } else if (Settings.ComputingAcceleration == ComputingAcceleration.PureCSParallelisation) { ProgressDescription = "Calculating block types..."; _terrainGenerator.CalculateBlockTypesParallel(); AlreadyGenerated += _progressStep * 3; yield return(null); } if (Settings.IsWater) { ProgressDescription = "Generating water..."; _terrainGenerator.AddWater(ref Blocks); } AlreadyGenerated += _progressStep; yield return(null); ProgressDescription = "Generating trees..."; _terrainGenerator.AddTreesParallel(Settings.TreeProbability); AlreadyGenerated += _progressStep; yield return(null); ProgressDescription = "Chunk data initialization..."; if (firstRun) { _worldScene = SceneManager.CreateScene(name); } // chunkData need to be initialized earlier in order to allow main loop iterate over chunks before their meshes are ready // thanks to this we can display chunk as soon as they become ready Chunks = new ChunkData[Settings.WorldSizeX, WORLD_SIZE_Y, Settings.WorldSizeZ]; for (int x = 0; x < Settings.WorldSizeX; x++) { for (int z = 0; z < Settings.WorldSizeZ; z++) { for (int y = 0; y < WORLD_SIZE_Y; y++) { Chunks[x, y, z] = new ChunkData(new Vector3Int(x, y, z), new Vector3Int(x * CHUNK_SIZE, y * CHUNK_SIZE, z * CHUNK_SIZE)); } } } ChunkObjects = new ChunkObject[Settings.WorldSizeX, WORLD_SIZE_Y, Settings.WorldSizeZ]; yield return(null); ProgressDescription = "Calculating faces..."; _meshGenerator.CalculateFaces(ref Blocks); AlreadyGenerated += _progressStep; yield return(null); ProgressDescription = "World boundaries check..."; _meshGenerator.WorldBoundariesCheck(ref Blocks); AlreadyGenerated += _progressStep; yield return(null); ProgressDescription = "Creating chunks..."; // create chunk objects one by one for (int x = 0; x < Settings.WorldSizeX; x++) { for (int z = 0; z < Settings.WorldSizeZ; z++) { for (int y = 0; y < WORLD_SIZE_Y; y++) { ChunkData chunkData = Chunks[x, y, z]; _meshGenerator.CalculateMeshes(ref Blocks, chunkData.Position, out Mesh terrainMesh, out Mesh waterMesh); if (firstRun) { var chunkObject = new ChunkObject(); CreateChunkGameObjects(ref chunkData, ref chunkObject, terrainMesh, waterMesh); SceneManager.MoveGameObjectToScene(chunkObject.Terrain.gameObject, _worldScene); SceneManager.MoveGameObjectToScene(chunkObject.Water.gameObject, _worldScene); ChunkObjects[x, y, z] = chunkObject; } else { SetMeshesAndCollider(ref chunkData, ref ChunkObjects[x, y, z], terrainMesh, waterMesh); } Chunks[x, y, z].Status = ChunkStatus.NeedToBeRedrawn; AlreadyGenerated++; yield return(null); // give back control } } } Status = WorldGeneratorStatus.AllReady; AlreadyGenerated += _progressStep; _stopwatch.Stop(); UnityEngine.Debug.Log($"It took {_stopwatch.ElapsedTicks / TimeSpan.TicksPerMillisecond} ms to generate the world."); ProgressDescription = "Generation Completed"; callback?.Invoke(); }
/// <summary> /// Generates block types with hp and hp level. /// Chunks and their objects (if first run = true). /// And calculates faces. /// </summary> public IEnumerator CreateWorld(bool firstRun, Action callback) { MainController.InitializeOnWorldSizeChange(); _stopwatch.Restart(); ResetProgressBarVariables(); ProgressDescription = "Initialization..."; Status = WorldGeneratorStatus.NotReady; GlobalVariables.Blocks = new BlockData[ GlobalVariables.Settings.WorldSizeX * Constants.CHUNK_SIZE, Constants.WORLD_SIZE_Y *Constants.CHUNK_SIZE, GlobalVariables.Settings.WorldSizeZ *Constants.CHUNK_SIZE]; AlreadyGenerated += _progressStep; yield return(null); // return control ProgressDescription = "Calculating block types..."; TerrainGenerationAbstractionLayer.CalculateBlockTypes(); AlreadyGenerated += _progressStep; yield return(null); // return control to update the UI if (GlobalVariables.Settings.IsWater) { ProgressDescription = "Generating water..."; TerrainGenerationAbstractionLayer.AddWater(); } AlreadyGenerated += _progressStep; yield return(null); // return control ProgressDescription = "Generating trees..."; TerrainGenerationAbstractionLayer.AddTrees(); AlreadyGenerated += _progressStep; yield return(null); // return control ProgressDescription = "Chunk data initialization..."; if (firstRun) { _worldScene = SceneManager.CreateScene(name); } // chunkData need to be initialized earlier in order to allow main loop iterate over chunks before their meshes are ready // thanks to this we can display chunk as soon as they become ready GlobalVariables.Chunks = new ChunkData[GlobalVariables.Settings.WorldSizeX, Constants.WORLD_SIZE_Y, GlobalVariables.Settings.WorldSizeZ]; for (int x = 0; x < GlobalVariables.Settings.WorldSizeX; x++) { for (int z = 0; z < GlobalVariables.Settings.WorldSizeZ; z++) { for (int y = 0; y < Constants.WORLD_SIZE_Y; y++) { GlobalVariables.Chunks[x, y, z] = new ChunkData( coord: new ReadonlyVector3Int(x, y, z), position: new ReadonlyVector3Int(x * Constants.CHUNK_SIZE, y * Constants.CHUNK_SIZE, z * Constants.CHUNK_SIZE)); } } } ChunkObjects = new ChunkObject[GlobalVariables.Settings.WorldSizeX, Constants.WORLD_SIZE_Y, GlobalVariables.Settings.WorldSizeZ]; yield return(null); // return control ProgressDescription = "Calculating faces..."; MeshGenerationAbstractionLayer.CalculateFaces(); AlreadyGenerated += _progressStep; yield return(null); // return control ProgressDescription = "World boundaries check..."; MeshGenerationAbstractionLayer.WorldBoundariesCheck(); AlreadyGenerated += _progressStep; yield return(null); // return control ProgressDescription = "Creating chunks..."; // create chunk objects one by one for (int x = 0; x < GlobalVariables.Settings.WorldSizeX; x++) { for (int z = 0; z < GlobalVariables.Settings.WorldSizeZ; z++) { for (int y = 0; y < Constants.WORLD_SIZE_Y; y++) { ChunkData chunkData = GlobalVariables.Chunks[x, y, z]; MeshGenerationAbstractionLayer.CalculateMeshes(in chunkData.Position, out Mesh terrainMesh, out Mesh waterMesh); if (firstRun) { var chunkObject = new ChunkObject(); CreateChunkGameObjects(ref chunkData, ref chunkObject, terrainMesh, waterMesh); SceneManager.MoveGameObjectToScene(chunkObject.Terrain.gameObject, _worldScene); SceneManager.MoveGameObjectToScene(chunkObject.Water.gameObject, _worldScene); ChunkObjects[x, y, z] = chunkObject; } else { SetMeshesAndCollider(ref chunkData, ref ChunkObjects[x, y, z], terrainMesh, waterMesh); } GlobalVariables.Chunks[x, y, z].Status = ChunkStatus.NeedToBeRedrawn; AlreadyGenerated++; yield return(null); // return control } } } Status = WorldGeneratorStatus.AllReady; AlreadyGenerated += _progressStep; _stopwatch.Stop(); UnityEngine.Debug.Log($"It took {_stopwatch.ElapsedTicks / TimeSpan.TicksPerMillisecond} ms to generate the world."); ProgressDescription = $"Generation Completed {_stopwatch.ElapsedTicks / TimeSpan.TicksPerMillisecond} ms"; callback?.Invoke(); }
/// <summary> /// Generates block types with hp and hp level. /// Chunks and their objects (if first run = true). /// And calculates faces. /// </summary> public IEnumerator LoadWorld(bool firstRun, Action callback) { ResetProgressBarVariables(); _stopwatch.Restart(); ProgressDescription = "Loading data..."; Status = WorldGeneratorStatus.NotReady; var storage = new PersistentStorage(CHUNK_SIZE); SaveGameData save = storage.LoadGame(); Settings.WorldSizeX = save.WorldSizeX; Settings.WorldSizeZ = save.WorldSizeZ; PlayerLoadedPosition = save.PlayerPosition; PlayerLoadedRotation = save.PlayerRotation; AlreadyGenerated += _progressStep; yield return(null); // give back control ProgressDescription = "Creating game objects..."; if (firstRun) { _worldScene = SceneManager.CreateScene(name); } Blocks = save.Blocks; Status = WorldGeneratorStatus.TerrainReady; AlreadyGenerated += _progressStep; yield return(null); // give back control if (firstRun) { ProgressDescription = "Chunk data initialization..."; // chunkData need to be initialized earlier in order to allow main loop iterate over chunks before their meshes are ready // thanks to this we can display chunk as soon as they become ready Chunks = new ChunkData[Settings.WorldSizeX, WORLD_SIZE_Y, Settings.WorldSizeZ]; for (int x = 0; x < Settings.WorldSizeX; x++) { for (int z = 0; z < Settings.WorldSizeZ; z++) { for (int y = 0; y < WORLD_SIZE_Y; y++) { Chunks[x, y, z] = new ChunkData( new Vector3Int(x, y, z), new Vector3Int(x * CHUNK_SIZE, y * CHUNK_SIZE, z * CHUNK_SIZE)); } } } ChunkObjects = new ChunkObject[Settings.WorldSizeX, WORLD_SIZE_Y, Settings.WorldSizeZ]; AlreadyGenerated += _progressStep; yield return(null); // give back control } ProgressDescription = "Calculating faces..."; _meshGenerator.CalculateFaces(ref Blocks); AlreadyGenerated += _progressStep; yield return(null); // give back control ProgressDescription = "World boundaries check..."; _meshGenerator.WorldBoundariesCheck(ref Blocks); Status = WorldGeneratorStatus.FacesReady; AlreadyGenerated += _progressStep; yield return(null); // give back control ProgressDescription = "Creating chunks..."; // create chunk objects one by one for (int x = 0; x < Settings.WorldSizeX; x++) { for (int z = 0; z < Settings.WorldSizeZ; z++) { for (int y = 0; y < WORLD_SIZE_Y; y++) { ChunkData chunkData = Chunks[x, y, z]; _meshGenerator.CalculateMeshes(ref Blocks, chunkData.Position, out Mesh terrainMesh, out Mesh waterMesh); if (firstRun) { var chunkObject = new ChunkObject(); CreateChunkGameObjects(ref chunkData, ref chunkObject, terrainMesh, waterMesh); SceneManager.MoveGameObjectToScene(chunkObject.Terrain.gameObject, _worldScene); SceneManager.MoveGameObjectToScene(chunkObject.Water.gameObject, _worldScene); ChunkObjects[x, y, z] = chunkObject; } else { SetMeshesAndCollider(ref chunkData, ref ChunkObjects[x, y, z], terrainMesh, waterMesh); } Chunks[x, y, z].Status = ChunkStatus.NeedToBeRedrawn; AlreadyGenerated++; yield return(null); // give back control } } } Status = WorldGeneratorStatus.AllReady; _stopwatch.Stop(); UnityEngine.Debug.Log($"It took {_stopwatch.ElapsedTicks / TimeSpan.TicksPerMillisecond} ms to load all terrain."); AlreadyGenerated = TerrainProgressSteps + MeshProgressSteps; // hardcoded end indicator ProgressDescription = "Game Load Completed"; callback?.Invoke(); }