using UnityEngine; using System.Collections; using System.Threading.Tasks; /// /// Generates mazes asynchronously to prevent blocking the main thread /// Useful for very large mazes that take time to generate /// public class AsyncMazeGenerator : MonoBehaviour { [Header("Generation Settings")] [SerializeField] private MazeController mazeController; [SerializeField] private bool generateOnStart = false; [Header("Progress")] [SerializeField] private UnityEngine.UI.Slider progressBar; [SerializeField] private TMPro.TextMeshProUGUI progressText; private bool isGenerating = false; private MazeData currentMaze; private int progressCompletedTiles = 0; private int progressTotalTiles = 0; private string progressMessage = ""; private readonly object progressLock = new object(); private int lastLoggedPercent = -1; void Start() { if (generateOnStart) { GenerateMazeAsync(); } } /// /// Starts asynchronous maze generation /// public void GenerateMazeAsync() { if (isGenerating) { Debug.LogWarning("Maze generation already in progress"); return; } StartCoroutine(GenerateMazeCoroutine()); } /// /// Coroutine that handles the async generation /// private IEnumerator GenerateMazeCoroutine() { isGenerating = true; UpdateProgress(0f, "Initializing..."); // Get config var config = mazeController.GetConfig(); if (config == null) { Debug.LogError("No maze config found"); isGenerating = false; yield break; } // Create generator with progress callback var generator = new MazeGenerator(config, OnProgressUpdate); // Generate in background thread Task generationTask = Task.Run(() => generator.Generate()); while (!generationTask.IsCompleted) { int completed; int total; string message; lock (progressLock) { completed = progressCompletedTiles; total = progressTotalTiles; message = progressMessage; } float progress = total > 0 ? completed / (float)total : 0f; UpdateProgress(progress, $"Generating maze... {completed}/{total} ({(int)(progress * 100)}%) {message}"); int percent = Mathf.Clamp((int)(progress * 100), 0, 100); if (percent != lastLoggedPercent) { Debug.Log($"Maze progress: {completed}/{total} tiles ({percent}%) - {message}"); lastLoggedPercent = percent; } yield return new WaitForSeconds(0.1f); } if (generationTask.IsFaulted) { Debug.LogError($"Maze generation failed: {generationTask.Exception}"); isGenerating = false; yield break; } currentMaze = generationTask.Result; mazeController.SetCurrentMaze(currentMaze); UpdateProgress(1f, "Complete!"); yield return new WaitForSeconds(0.5f); // Show completion briefly UpdateProgress(0f, "Ready"); isGenerating = false; Debug.Log($"Async maze generation complete: {currentMaze.Width}x{currentMaze.Height}"); } /// /// Updates progress UI /// private void UpdateProgress(float progress, string message) { if (progressBar != null) { progressBar.value = progress; } if (progressText != null) { progressText.text = message; } } private void OnProgressUpdate(int completedTiles, int totalTiles, string message) { lock (progressLock) { progressCompletedTiles = completedTiles; progressTotalTiles = totalTiles; progressMessage = message; } } /// /// Checks if generation is in progress /// public bool IsGenerating() { return isGenerating; } /// /// Gets the most recently generated maze /// public MazeData GetCurrentMaze() { return currentMaze; } }