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;
}
}