181 lines
6.4 KiB
C#
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()
|
|
};
|
|
}
|
|
}
|
|
} |