using System; using System.Collections; using System.Collections.Generic; using Unity.Mathematics; using UnityEngine; using Random = UnityEngine.Random; public class MapGenerator : MonoBehaviour { public MapConfigSO mapConfig1; public MapConfigSO mapConfig2; public MapConfigSO mapConfig3; public Room roomPrefab; public LineRenderer linePrefab; private MapConfigSO mapConfig; private float screenHeight; private float screenWidth; private float columnWidth; public float border; private float distanceToCamera; private List rooms = new(); private List lines = new(); [Header("学习参数")] public int studyAbility = 1; private void Awake() { Camera cam = Camera.main; ChooseMap(); // 计算当前物体所在平面到相机的距离 distanceToCamera = Mathf.Abs(cam.transform.position.z - transform.position.z); // 根据透视相机计算可视范围 screenHeight = 2f * distanceToCamera * Mathf.Tan(cam.fieldOfView * 0.5f * Mathf.Deg2Rad); screenWidth = screenHeight * cam.aspect; // 修复:考虑边框,计算实际可用宽度和列间距 int columnCount = mapConfig.roomBlueprints.Count; float availableWidth = screenWidth - (border * 2); // 减去左右边框占用的宽度 columnWidth = availableWidth / (columnCount + 1); // 这里+1是为了在首尾也留出边距 } private void Start() { CreateMap(); } public void ChooseMap() { if(studyAbility <= 5) { mapConfig = mapConfig1; }else if(studyAbility <= 10) { mapConfig = mapConfig2; } else { mapConfig = mapConfig3; } } public void CreateMap() { List previousColumnRooms = new(); float left = -screenWidth / 2f; float top = screenHeight / 2f; for (int column = 0; column < mapConfig.roomBlueprints.Count; column++) { var blueprint = mapConfig.roomBlueprints[column]; int amount = Random.Range(blueprint.min, blueprint.max); float roomGapY = screenHeight / (amount + 1); // 修复:重新计算x坐标,确保所有列都在可视范围内 // 使用插值方式,第一列在左边距+border处,最后一列在右边距-border处 float t = (float)column / (mapConfig.roomBlueprints.Count - 1); // 0到1之间的比例 float x = left + border + (screenWidth - border * 2) * t; List currentColumnRooms = new(); for (int i = 0; i < amount; i++) { float y = top - roomGapY * (i + 1); Vector3 pos = new Vector3( x, y, transform.position.z ); var room = Instantiate(roomPrefab, pos, Quaternion.identity, transform); currentColumnRooms.Add(room); rooms.Add(room); } if (previousColumnRooms.Count > 0) { CreateConnections(previousColumnRooms,currentColumnRooms); } previousColumnRooms = currentColumnRooms; } } private void CreateConnections(List column1, List column2) { HashSet connectedColumn2Rooms = new(); foreach (var room in column1) { var targetRoom = ConnectToRandomRoom(room,column2); connectedColumn2Rooms.Add(targetRoom); } foreach (var room in column2) { if (!connectedColumn2Rooms.Contains(room)) { ConnectToRandomRoom(room,column1); } } } private Room ConnectToRandomRoom(Room room, List column2) { Room targetRoom; targetRoom = column2[Random.Range(0, column2.Count)]; var line = Instantiate(linePrefab, transform); line.SetPosition(0, room.transform.position); line.SetPosition(1, targetRoom.transform.position); lines.Add(line); return targetRoom; } [ContextMenu("ReGenerateRoom")] public void ReGenerateRoom() { ChooseMap(); foreach (var room in rooms) { Destroy(room.gameObject); } foreach (var line in lines) { Destroy(line.gameObject); } rooms.Clear(); lines.Clear(); CreateMap(); } }