MapGenerator.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using Unity.Mathematics;
  5. using UnityEngine;
  6. using Random = UnityEngine.Random;
  7. public class MapGenerator : MonoBehaviour
  8. {
  9. public MapConfigSO mapConfig1;
  10. public MapConfigSO mapConfig2;
  11. public MapConfigSO mapConfig3;
  12. public Room roomPrefab;
  13. public LineRenderer linePrefab;
  14. private MapConfigSO mapConfig;
  15. private float screenHeight;
  16. private float screenWidth;
  17. private float columnWidth;
  18. public float border;
  19. private float distanceToCamera;
  20. private List<Room> rooms = new();
  21. private List<LineRenderer> lines = new();
  22. [Header("学习参数")] public int studyAbility = 1;
  23. private void Awake()
  24. {
  25. Camera cam = Camera.main;
  26. ChooseMap();
  27. // 计算当前物体所在平面到相机的距离
  28. distanceToCamera = Mathf.Abs(cam.transform.position.z - transform.position.z);
  29. // 根据透视相机计算可视范围
  30. screenHeight = 2f * distanceToCamera * Mathf.Tan(cam.fieldOfView * 0.5f * Mathf.Deg2Rad);
  31. screenWidth = screenHeight * cam.aspect;
  32. // 修复:考虑边框,计算实际可用宽度和列间距
  33. int columnCount = mapConfig.roomBlueprints.Count;
  34. float availableWidth = screenWidth - (border * 2); // 减去左右边框占用的宽度
  35. columnWidth = availableWidth / (columnCount + 1); // 这里+1是为了在首尾也留出边距
  36. }
  37. private void Start()
  38. {
  39. CreateMap();
  40. }
  41. public void ChooseMap()
  42. {
  43. if(studyAbility <= 5)
  44. {
  45. mapConfig = mapConfig1;
  46. }else if(studyAbility <= 10)
  47. {
  48. mapConfig = mapConfig2;
  49. }
  50. else
  51. {
  52. mapConfig = mapConfig3;
  53. }
  54. }
  55. public void CreateMap()
  56. {
  57. List<Room> previousColumnRooms = new();
  58. float left = -screenWidth / 2f;
  59. float top = screenHeight / 2f;
  60. for (int column = 0; column < mapConfig.roomBlueprints.Count; column++)
  61. {
  62. var blueprint = mapConfig.roomBlueprints[column];
  63. int amount = Random.Range(blueprint.min, blueprint.max);
  64. float roomGapY = screenHeight / (amount + 1);
  65. // 修复:重新计算x坐标,确保所有列都在可视范围内
  66. // 使用插值方式,第一列在左边距+border处,最后一列在右边距-border处
  67. float t = (float)column / (mapConfig.roomBlueprints.Count - 1); // 0到1之间的比例
  68. float x = left + border + (screenWidth - border * 2) * t;
  69. List<Room> currentColumnRooms = new();
  70. for (int i = 0; i < amount; i++)
  71. {
  72. float y = top - roomGapY * (i + 1);
  73. Vector3 pos = new Vector3(
  74. x,
  75. y,
  76. transform.position.z
  77. );
  78. var room = Instantiate(roomPrefab, pos, Quaternion.identity, transform);
  79. currentColumnRooms.Add(room);
  80. rooms.Add(room);
  81. }
  82. if (previousColumnRooms.Count > 0)
  83. {
  84. CreateConnections(previousColumnRooms,currentColumnRooms);
  85. }
  86. previousColumnRooms = currentColumnRooms;
  87. }
  88. }
  89. private void CreateConnections(List<Room> column1, List<Room> column2)
  90. {
  91. HashSet<Room> connectedColumn2Rooms = new();
  92. foreach (var room in column1)
  93. {
  94. var targetRoom = ConnectToRandomRoom(room,column2);
  95. connectedColumn2Rooms.Add(targetRoom);
  96. }
  97. foreach (var room in column2)
  98. {
  99. if (!connectedColumn2Rooms.Contains(room))
  100. {
  101. ConnectToRandomRoom(room,column1);
  102. }
  103. }
  104. }
  105. private Room ConnectToRandomRoom(Room room, List<Room> column2)
  106. {
  107. Room targetRoom;
  108. targetRoom = column2[Random.Range(0, column2.Count)];
  109. var line = Instantiate(linePrefab, transform);
  110. line.SetPosition(0, room.transform.position);
  111. line.SetPosition(1, targetRoom.transform.position);
  112. lines.Add(line);
  113. return targetRoom;
  114. }
  115. [ContextMenu("ReGenerateRoom")]
  116. public void ReGenerateRoom()
  117. {
  118. ChooseMap();
  119. foreach (var room in rooms)
  120. {
  121. Destroy(room.gameObject);
  122. }
  123. foreach (var line in lines)
  124. {
  125. Destroy(line.gameObject);
  126. }
  127. rooms.Clear();
  128. lines.Clear();
  129. CreateMap();
  130. }
  131. }