/// <summary> /// Delegates the generation to the underlying view models. /// Displays the generated content using the unity objects /// </summary> /// <param name="finishAction">The action to invoke when the generation is completed.</param> /// <param name="generationStartAction">The action to invoke when a generation starts.</param> /// <param name="generationEndAction">The action to invoke when a generation ends.</param> /// <param name="cancellationToken">The cancellation token, used to cancel the generation.</param> internal async void GenerateAsync( Action finishAction, OnGenerationStart generationStartAction, OnGenerationEnd generationEndAction, CancellationToken cancellationToken) { Reset(); _finishedGenerations = 0; _onGenerationStart = generationStartAction; _onGenerationEnd = generationEndAction; // Invokes the finish action void OnGenerationFinish() => finishAction?.Invoke(); // Update the cancellation token of the view models terrainViewModel.CancelToken = cancellationToken; cityViewModel.CancelToken = cancellationToken; try { // Generate the terrain var(terrainMesh, terrainTexture) = await Task.Run(() => terrainViewModel.Generate(), cancellationToken); if (cancellationToken.IsCancellationRequested || terrainMesh == null || terrainTexture == null) { // Either the task was cancelled or a terrain value is null, abort. OnGenerationFinish(); return; } // Update component data _meshFilter.sharedMesh = terrainMesh; _meshCollider.sharedMesh = terrainMesh; _meshRenderer.sharedMaterial.mainTexture = terrainTexture; // Update the model's terrain data _model.TerrainTexture = terrainTexture; _model.TerrainHeightMap = _meshFilter.sharedMesh.HeightMap(); _model.TerrainOffset = _meshFilter.transform.position; // Generate a city _model.City = await Task.Run(() => cityViewModel.Generate(), cancellationToken); } catch (TaskCanceledException) { // A task was canceled, abort OnGenerationFinish(); return; } if (cancellationToken.IsCancellationRequested || _model.City == null) { // Either the task was canceled or the city is not valid, abort. OnGenerationFinish(); return; } // Create game objects based on the world data (terrain and city elements) CreateGameObjects(cancellationToken); // Invoke the finish action OnGenerationFinish(); }