using System.Collections; using System.Collections.Generic; using UnityEngine; namespace Hallucinate.GameSetup.Maze { /// /// Central controller for the Maze system. /// Manages algorithm selection, debug speed, and regeneration. /// public class MazeManager : MonoBehaviour { public enum AlgorithmType { Recursive, Wilsons, Prims, Crawler } [Header("System Settings")] public MazeGrid[] mazes; public float floorHeight = 3.5f; public int connectionsPerFloor = 2; [SerializeField] private AlgorithmType selectedAlgorithm; [SerializeField] private int width = 30; [SerializeField] private int depth = 30; [Header("Debug Settings")] [SerializeField] private bool debugMode = true; [Range(0.001f, 0.5f)] [SerializeField] private float visualizationInterval = 0.05f; [Header("References")] [SerializeField] private MazeRenderer mazeRenderer; [SerializeField] private Transform mazeContainer; [Header("Corridor Setting")] public GameObject straightManHoleLadder; public GameObject straightManHoleUp; public GameObject deadendManHoleLadder; public GameObject deadendManHoleUp; private MazeGrid _grid; private Coroutine _generationCoroutine; private void Start() { Regenerate(); } private void Update() { if (Input.GetKeyDown(KeyCode.R)) { Regenerate(); } } [ContextMenu("Regenerate")] public void Regenerate() { // Bước 1: Khởi tạo tất cả các tầng mê cung for (int i = 0; i < mazes.Length; i++) { mazes[i].width = width; mazes[i].depth = depth; mazes[i].level = i; mazes[i].Build(); // Lưu ý: Hàm Build này của bạn nên được tối ưu để KHÔNG Instantiate Model vội. } // Bước 2: Tạo điểm nối giữa các cặp tầng (0->1, 1->2, 2->3...) for (int i = 0; i < mazes.Length - 1; i++) { MazeGrid currentFloor = mazes[i]; MazeGrid nextFloor = mazes[i + 1]; // 2.1: Quét tìm TẤT CẢ các tọa độ (x, z) có thể làm điểm nối List possibleConnections = new List(); for (int z = 0; z < depth; z++) { for (int x = 0; x < width; x++) { // Nếu cả Tầng Dưới và Tầng Trên đều đang là đường đi (Path) ở tọa độ này // (Bạn cần đổi điều kiện này cho khớp với Enum/Class thực tế của bạn) bool isCurrentFloorPath = currentFloor.piecePlace[x, z].piece == MazeGrid.PieceType.Vertical_Straight; bool isNextFloorPath = nextFloor.piecePlace[x, z].piece == MazeGrid.PieceType.Vertical_Straight; if (isCurrentFloorPath && isNextFloorPath) { possibleConnections.Add(new Vector2Int(x, z)); } } } // 2.2: Chọn ngẫu nhiên N điểm từ danh sách để làm thang nối int connectionsMade = 0; // Trộn ngẫu nhiên danh sách (Shuffle) để các điểm nối không bị dồn về 1 góc ShuffleList(possibleConnections); foreach (Vector2Int pos in possibleConnections) { if (connectionsMade >= connectionsPerFloor) break; // Đã đủ số lượng đường lên thì dừng int x = pos.x; int z = pos.y; // Xóa model đường đi cũ (nếu hàm Build() đã lỡ Instantiate) if (currentFloor.piecePlace[x, z].model != null) Destroy(currentFloor.piecePlace[x, z].model); if (nextFloor.piecePlace[x, z].model != null) Destroy(nextFloor.piecePlace[x, z].model); // TÍNH TOẠ ĐỘ Y CHUẨN XÁC: Y = Tầng * Độ_Cao_Tầng Vector3 upManHolePos = new Vector3(x * currentFloor.scale, currentFloor.level * floorHeight, z * currentFloor.scale); Vector3 ladderManPos = new Vector3(x * nextFloor.scale, nextFloor.level * floorHeight, z * nextFloor.scale); // Sinh Model mới tại điểm đã chốt currentFloor.piecePlace[x, z].model = Instantiate(straightManHoleUp, upManHolePos, Quaternion.identity); nextFloor.piecePlace[x, z].model = Instantiate(straightManHoleLadder, ladderManPos, Quaternion.identity); // Cập nhật loại dữ liệu để hệ thống ghi nhận đây là ô cầu thang // currentFloor.piecePlace[x, z].piece = Maze.PieceType.StairsUp; (Nếu bạn có enum này) connectionsMade++; } } if (_generationCoroutine != null) { StopCoroutine(_generationCoroutine); } mazeRenderer.Clear(); _grid = new MazeGrid(width, depth); mazeRenderer.Initialize(_grid, mazeContainer); IMazeAlgorithm algorithm = GetAlgorithm(selectedAlgorithm); if (debugMode) { _generationCoroutine = StartCoroutine(algorithm.GenerateStepByStep(_grid, visualizationInterval)); } else { algorithm.Generate(_grid); } } 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() }; } } }