Files
BABA_YAGA/Assets/Scripts/GameSetup/Maze/MazeManager.cs
2026-05-08 08:56:47 +07:00

181 lines
6.4 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Hallucinate.GameSetup.Maze
{
/// <summary>
/// Central controller for the Multi-floor Maze system.
/// Handles initialization order and cross-floor connections.
/// </summary>
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<MazeGrid> _mazeFloors = new List<MazeGrid>();
private List<MazeRenderer> _activeRenderers = new List<MazeRenderer>();
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<Vector2Int> overlapPaths = new List<Vector2Int>();
// 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<T>(List<T> 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()
};
}
}
}