AsyncMazeGenerator.cs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Threading.Tasks;
  4. /// <summary>
  5. /// Generates mazes asynchronously to prevent blocking the main thread
  6. /// Useful for very large mazes that take time to generate
  7. /// </summary>
  8. public class AsyncMazeGenerator : MonoBehaviour
  9. {
  10. [Header("Generation Settings")]
  11. [SerializeField] private MazeController mazeController;
  12. [SerializeField] private bool generateOnStart = false;
  13. [Header("Progress")]
  14. [SerializeField] private UnityEngine.UI.Slider progressBar;
  15. [SerializeField] private TMPro.TextMeshProUGUI progressText;
  16. private bool isGenerating = false;
  17. private MazeData currentMaze;
  18. private int progressCompletedTiles = 0;
  19. private int progressTotalTiles = 0;
  20. private string progressMessage = "";
  21. private readonly object progressLock = new object();
  22. private int lastLoggedPercent = -1;
  23. void Start()
  24. {
  25. if (generateOnStart)
  26. {
  27. GenerateMazeAsync();
  28. }
  29. }
  30. /// <summary>
  31. /// Starts asynchronous maze generation
  32. /// </summary>
  33. public void GenerateMazeAsync()
  34. {
  35. if (isGenerating)
  36. {
  37. Debug.LogWarning("Maze generation already in progress");
  38. return;
  39. }
  40. StartCoroutine(GenerateMazeCoroutine());
  41. }
  42. /// <summary>
  43. /// Coroutine that handles the async generation
  44. /// </summary>
  45. private IEnumerator GenerateMazeCoroutine()
  46. {
  47. isGenerating = true;
  48. UpdateProgress(0f, "Initializing...");
  49. // Get config
  50. var config = mazeController.GetConfig();
  51. if (config == null)
  52. {
  53. Debug.LogError("No maze config found");
  54. isGenerating = false;
  55. yield break;
  56. }
  57. // Create generator with progress callback
  58. var generator = new MazeGenerator(config, OnProgressUpdate);
  59. // Generate in background thread
  60. Task<MazeData> generationTask = Task.Run(() => generator.Generate());
  61. while (!generationTask.IsCompleted)
  62. {
  63. int completed;
  64. int total;
  65. string message;
  66. lock (progressLock)
  67. {
  68. completed = progressCompletedTiles;
  69. total = progressTotalTiles;
  70. message = progressMessage;
  71. }
  72. float progress = total > 0 ? completed / (float)total : 0f;
  73. UpdateProgress(progress, $"Generating maze... {completed}/{total} ({(int)(progress * 100)}%) {message}");
  74. int percent = Mathf.Clamp((int)(progress * 100), 0, 100);
  75. if (percent != lastLoggedPercent)
  76. {
  77. Debug.Log($"Maze progress: {completed}/{total} tiles ({percent}%) - {message}");
  78. lastLoggedPercent = percent;
  79. }
  80. yield return new WaitForSeconds(0.1f);
  81. }
  82. if (generationTask.IsFaulted)
  83. {
  84. Debug.LogError($"Maze generation failed: {generationTask.Exception}");
  85. isGenerating = false;
  86. yield break;
  87. }
  88. currentMaze = generationTask.Result;
  89. mazeController.SetCurrentMaze(currentMaze);
  90. UpdateProgress(1f, "Complete!");
  91. yield return new WaitForSeconds(0.5f); // Show completion briefly
  92. UpdateProgress(0f, "Ready");
  93. isGenerating = false;
  94. Debug.Log($"Async maze generation complete: {currentMaze.Width}x{currentMaze.Height}");
  95. }
  96. /// <summary>
  97. /// Updates progress UI
  98. /// </summary>
  99. private void UpdateProgress(float progress, string message)
  100. {
  101. if (progressBar != null)
  102. {
  103. progressBar.value = progress;
  104. }
  105. if (progressText != null)
  106. {
  107. progressText.text = message;
  108. }
  109. }
  110. private void OnProgressUpdate(int completedTiles, int totalTiles, string message)
  111. {
  112. lock (progressLock)
  113. {
  114. progressCompletedTiles = completedTiles;
  115. progressTotalTiles = totalTiles;
  116. progressMessage = message;
  117. }
  118. }
  119. /// <summary>
  120. /// Checks if generation is in progress
  121. /// </summary>
  122. public bool IsGenerating()
  123. {
  124. return isGenerating;
  125. }
  126. /// <summary>
  127. /// Gets the most recently generated maze
  128. /// </summary>
  129. public MazeData GetCurrentMaze()
  130. {
  131. return currentMaze;
  132. }
  133. }