using System.Collections; using System.Collections.Generic; using UnityEngine; namespace Hallucinate.GameSetup.Maze { /// /// Central controller for the Multi-floor Maze system. /// Handles initialization order and cross-floor connections. /// public class MazeManager : MonoBehaviour { public enum AlgorithmType { Recursive, Wilsons, Prims, Crawler } [Header("System Settings")] [Tooltip("Số lượng tầng mê cung cần sinh ra")] [Range(1, 10)] public int floorCount = 2; public float floorHeight = 4.0f; public int connectionsPerFloor = 2; [Header("Grid Settings")] [SerializeField] private AlgorithmType selectedAlgorithm; [SerializeField] private int width = 20; [SerializeField] private int depth = 20; [Header("References")] [SerializeField] private MazeRenderer rendererPrefab; [SerializeField] private Transform mazeContainer; private List _mazeFloors = new List(); private List _activeRenderers = new List(); private void Start() { Debug.Log("--- Tớ là: " + gameObject.name + " đang gọi Regenerate! ---"); Regenerate(); } private void Update() { if (Input.GetKeyDown(KeyCode.R)) { Regenerate(); } } //[ContextMenu("Regenerate")] public void Regenerate() { StopAllCoroutines(); ClearExistingMaze(); // 1. Khởi tạo dữ liệu các tầng (Logic Data) for (int i = 0; i < floorCount; i++) { // FIX: Khởi tạo Object trước khi gán thuộc tính MazeGrid newFloor = new MazeGrid(width, depth); newFloor.Level = i; // 2. Chạy thuật toán sinh mê cung cho tầng này (Sync để đảm bảo có dữ liệu trước khi nối tầng) IMazeAlgorithm algorithm = GetAlgorithm(selectedAlgorithm); algorithm.Generate(newFloor); _mazeFloors.Add(newFloor); } // 3. Tạo điểm nối cầu thang (Stairs) giữa các tầng kề nhau ConnectFloors(); // 4. Hiển thị 3D cho tất cả các tầng RenderAllFloors(); } private void ConnectFloors() { if (_mazeFloors.Count < 2) return; for (int i = 0; i < _mazeFloors.Count - 1; i++) { MazeGrid currentFloor = _mazeFloors[i]; MazeGrid nextFloor = _mazeFloors[i + 1]; List overlapPaths = new List(); // Tìm các tọa độ (x, z) mà cả 2 tầng đều là đường đi (Corridor) for (int z = 1; z < depth - 1; z++) { for (int x = 1; x < width - 1; x++) { if (currentFloor.GetCell(x, z) == MazeCellType.Corridor && nextFloor.GetCell(x, z) == MazeCellType.Corridor) { overlapPaths.Add(new Vector2Int(x, z)); } } } // Trộn ngẫu nhiên danh sách để điểm nối rải rác ShuffleList(overlapPaths); int actualConnections = Mathf.Min(connectionsPerFloor, overlapPaths.Count); for (int j = 0; j < actualConnections; j++) { Vector2Int pos = overlapPaths[j]; // Đánh dấu logic để Renderer tự chọn Prefab cầu thang từ VisualProfile currentFloor.SetCell(pos.x, pos.y, MazeCellType.StairsUp); nextFloor.SetCell(pos.x, pos.y, MazeCellType.StairsDown); } } } private void RenderAllFloors() { Debug.Log("--- Đang chạy hàm này! ---"); for (int i = 0; i < _mazeFloors.Count; i++) { if (_activeRenderers.Count > 100) { Debug.LogError("DỪNG LẠI! Quá nhiều tầng rồi!"); return; } // Tạo một Renderer instance cho mỗi tầng MazeRenderer floorRenderer = Instantiate(rendererPrefab, mazeContainer); floorRenderer.gameObject.name = $"Floor_Renderer_{i}"; // Đặt vị trí Y của tầng floorRenderer.transform.localPosition = new Vector3(0, i * floorHeight, 0); // Khởi tạo hiển thị cho Grid tương ứng floorRenderer.Initialize(_mazeFloors[i], floorRenderer.transform); _activeRenderers.Add(floorRenderer); } } private void ClearExistingMaze() { foreach (var renderer in _activeRenderers) { if (renderer != null) { renderer.Clear(); Destroy(renderer.gameObject); } } _activeRenderers.Clear(); _mazeFloors.Clear(); // Xóa sạch các object con cũ trong container (nếu có) if (mazeContainer != null) { foreach (Transform child in mazeContainer) { Destroy(child.gameObject); } } } private void ShuffleList(List list) { for (int i = 0; i < list.Count; i++) { T temp = list[i]; int randomIndex = Random.Range(i, list.Count); list[i] = list[randomIndex]; list[randomIndex] = temp; } } private IMazeAlgorithm GetAlgorithm(AlgorithmType type) { return type switch { AlgorithmType.Recursive => new RecursiveAlgorithm(), AlgorithmType.Wilsons => new WilsonsAlgorithm(), AlgorithmType.Prims => new PrimsAlgorithm(), AlgorithmType.Crawler => new CrawlerAlgorithm(), _ => new RecursiveAlgorithm() }; } } }