Unity 隨機房間地圖生成

不管是在迷宮仍是相似於地牢的遊戲地圖中,利用程序來生成每次都不同的地圖是一件叫人興奮不已的事。數據結構

這時咱們須要解決兩個很是重要的隨機事件:dom

1.在必定範圍內隨機出各不相同但又不能互相重疊的房間ide

2.優美生成鏈接這些房間的通道ui

 

基本的UML思路圖:spa

 

 

此次咱們先討論如何快速生成符合各類隨機要求的房間。code

通常來講,一個房間的高度是一個相對固定的值,能夠根據面板上的參數進行必要的調整,而真正參與隨機的應該是房間的長,寬和位置。orm

 

創建房間的數據結構,根據需求能夠隨時補充和添加:blog

 1 using System.Collections.Generic;
 2 using UnityEngine;
 3 
 4 public class RoomData
 5 {
 6     public int Id;
 7     //房間的Transform等屬性
 8     public RoomTran RoomTran;
 9     //該房間的戰鬥類型
10     public RoomBattleType BattleType;
11     //該房間與哪些其他房間互相鏈接
12     public List<RoomData> CrossRooms;
13     //房間內的怪物列表
14     public List<GameObject> Monsters;
15     //是不是端點房間
16     public bool bEndRoom;
17     //是不是主路徑房間
18     public bool bMainCrossRoom;
19 }
20 
21 public class RoomTran
22 {
23     public int Length;
24     public int Width;
25     //長寬中心點
26     public Vector2Int CenterPos;
27     //高度位置
28     public float PosY;
29 }
30 
31 public enum RoomBattleType
32 {
33     Rest,
34     NormalBattle,
35     BossBattle
36 }

 

RoonBuilder屬性和控制參數:遊戲

 1     //建築單位方塊
 2     public GameObject BuildUnit;
 3 
 4     //房間高度值
 5     public int FixedUnitHeight;
 6     //生成的房間層數
 7     public int LayerCount;
 8     //長寬隨機範圍
 9     public Vector2Int GenRange;
10 
11     //隨機類型
12     public RoomRandType RandType;
13     //隨機的房間形狀類型
14     public RoomShapeType Shape;
15 
16     //房間大小的隨機列表,用於枚舉隨機
17     public List<Vector2Int> RoomRandSizes = new List<Vector2Int>();
18 
19     //隨機的房間最大面積
20     public int MaxRoomArea;
21     //最大隨機數量(隨機試驗次數)
22     public int MaxRoomCount;
23 
24     //最小邊長度
25     private int MinRoomEdge;
26     //最大長寬比
27     public int MaxLengthWidthScale = 2;
28 
29     //標準方向
30     Vector3Int Dx = new Vector3Int(1, 0, 0);
31     Vector3Int Dy = new Vector3Int(0, 1, 0);
32     Vector3Int Dz = new Vector3Int(0, 0, 1);
33 
34     //建築單位標籤
35     const string S_TAG = "Unit";
36 
37     private MapSystem MapManager;

 

單房間輪廓生成:事件

 1     /// <summary>
 2     /// 生成單一房間的輪廓
 3     /// </summary>
 4     /// <param name="centerPos">房間中點位置</param>
 5     /// <param name="length"></param>
 6     /// <param name="width"></param>
 7     /// <param name="parent">父物體</param>
 8     void GenOneRoom(Vector3 centerPos, int length, int width, Transform parent = null)
 9     {
10         var to = new Vector3(length - 1, FixedUnitHeight - 1, width - 1) * .5f;
11 
12         //頂點
13         var ned = centerPos - to;
14         var fod = centerPos + to;
15 
16         var v3 = new Vector3(ned.x, fod.y, ned.z);
17         var v4 = new Vector3(ned.x, fod.y, fod.z);
18         var v5 = new Vector3(ned.x, ned.y, fod.z);
19 
20         var v6 = new Vector3(fod.x, ned.y, ned.z);
21         var v7 = new Vector3(fod.x, ned.y, fod.z);
22         var v8 = new Vector3(fod.x, fod.y, ned.z);
23 
24         //頂點位置(8個)
25         InsSetPos(ned, parent);
26         InsSetPos(fod, parent);
27         InsSetPos(v3, parent);
28         InsSetPos(v4, parent);
29         InsSetPos(v5, parent);
30         InsSetPos(v6, parent);
31         InsSetPos(v7, parent);
32         InsSetPos(v8, parent);
33 
34         //12條棱(4*3)
35         //
36         InsOneEdge(length, ned, Dx, parent);
37         InsOneEdge(length, v3, Dx, parent);
38         InsOneEdge(length, v4, Dx, parent);
39         InsOneEdge(length, v5, Dx, parent);
40         //
41         InsOneEdge(FixedUnitHeight, ned, Dy, parent);
42         InsOneEdge(FixedUnitHeight, v5, Dy, parent);
43         InsOneEdge(FixedUnitHeight, v6, Dy, parent);
44         InsOneEdge(FixedUnitHeight, v7, Dy, parent);
45         //
46         InsOneEdge(width, ned, Dz, parent);
47         InsOneEdge(width, v3, Dz, parent);
48         InsOneEdge(width, v6, Dz, parent);
49         InsOneEdge(width, v8, Dz, parent);
50     }
51 
52     //生成一條邊上的建築單位但不包含頂點位置
53     void InsOneEdge(int edge, Vector3 v, Vector3 dir, Transform parent = null)
54     {
55         //忽略首尾單位
56         for (int i = 1; i < edge - 1; i++)
57         {
58             InsSetPos(v + i * dir, parent);
59         }
60     }
61 
62     void InsSetPos(Vector3 pos, Transform parent = null)
63     {
64         var ins = Instantiate(BuildUnit);
65         ins.transform.position = pos;
66         ins.transform.parent = parent;
67     }

這裏惟一值得注意的地方是房間頂點位置的單位不要重複生成。(由於想偷懶的話真的很容易重複Orz)。

 

隨機RoomTran結構:

 1     RoomTran RanRoomTran(Vector3 centerPos)
 2     {
 3         var rt = new RoomTran();
 4 
 5         switch (RandType)
 6         {
 7             case RoomRandType.AllRand:
 8                 int temp;
 9                 var oe = MaxRoomArea / MinRoomEdge;
10                 switch (Shape)
11                 {
12                     case RoomShapeType.LengthMain:
13                         rt.Length = Random.Range(MinRoomEdge + 1, oe + 1);
14                         temp = MaxRoomArea / rt.Length;
15                         if (temp >= rt.Length)
16                             rt.Width = Random.Range(MinRoomEdge, rt.Length);
17                         else
18                             rt.Width = Random.Range(MinRoomEdge, temp + 1);
19                         break;
20                     case RoomShapeType.WidthMain:
21                         rt.Width = Random.Range(MinRoomEdge + 1, oe + 1);
22                         temp = MaxRoomArea / rt.Width;
23                         if (temp >= rt.Width)
24                             rt.Length = Random.Range(MinRoomEdge, rt.Width);
25                         else
26                             rt.Length = Random.Range(MinRoomEdge, temp + 1);
27                         break;
28                     case RoomShapeType.Coustom:
29                         rt.Length = Random.Range(MinRoomEdge, oe + 1);
30                         temp = MaxRoomArea / rt.Length;
31                         rt.Width = Random.Range(MinRoomEdge, temp + 1);
32                         break;
33                 }
34                 break;
35             case RoomRandType.EnumRand:
36                 var rc = RoomRandSizes.Count;
37                 if (rc == 0)
38                 {
39                     //未填寫時設定隨機默認值
40                     rt.Length = 3;
41                     rt.Width = 3;
42                 }
43                 else
44                 {
45                     var ridx = Random.Range(0,rc);
46                     var t = RoomRandSizes[ridx];
47                     if (t.x < 3 || t.y < 3)
48                     {
49                         //填寫錯誤時設定隨機默認值
50                         rt.Length = 3;
51                         rt.Width = 3;
52                     }
53                     else
54                     {
55                         switch (Shape)
56                         {
57                             case RoomShapeType.LengthMain:
58                                 rt.Length = t.x > t.y ? t.x : t.y;
59                                 rt.Width = t.x < t.y ? t.x : t.y;
60                                 break;
61                             case RoomShapeType.WidthMain:
62                                 rt.Width = t.x > t.y ? t.x : t.y;
63                                 rt.Length = t.x < t.y ? t.x : t.y;
64                                 break;
65                             case RoomShapeType.Coustom:
66                                 rt.Length = Random.value < .5f ? t.x : t.y;
67                                 rt.Width = t.y == rt.Length ? t.x : t.y;
68                                 break;
69                         }         
70                     }
71                 }
72                 break;
73         }
74    
75         rt.CenterPos = new Vector2Int(Random.Range((int)(centerPos.x - GenRange.x * .5f), (int)(centerPos.x + GenRange.x * .5f)),
76             Random.Range((int)(centerPos.z - GenRange.y * .5f), (int)(centerPos.z + GenRange.y * .5f)));
77 
78         rt.PosY = centerPos.y;
79 
80         var roomCenter = new Vector3(rt.CenterPos.x, rt.PosY, rt.CenterPos.y);
81 
82         //射線檢測重疊
83         if (RayRoomCheck(roomCenter, rt.Length, rt.Width))
84         {
85             return null;
86         }
87         return rt;
88     }

用的是射線檢測重疊,生成了重疊的房間就會被視做是一次失敗的隨機試驗,以前嘗試過直接用物理系統推開失敗了,多是使用有誤,若是有知道緣由的歡迎與筆者分享,共同進步;

固然了,你也能夠用Unity自帶的Bounds.Intersects(Bounds other)方法來判斷兩個生成的房間盒子是否重疊,但缺點是沒有辦法控制兩個房間邊緣的間隔的最小距離,用純粹的數學方法判斷三個軸向的邊緣值大小一樣也是可行的:

 1     //生成房間前射線檢測下範圍內有無其餘房間
 2     bool RayRoomCheck(Vector3 cp, int length, int width)
 3     {
 4         bool result = false;
 5         //長寬至少留一格間隙,高度與地板格對齊
 6         var to = new Vector3(length + 1, FixedUnitHeight - 1, width + 1) * .5f;
 7         var ned = cp - to;
 8 
 9         var vx2 = ned + new Vector3(0, 0, width + 1) * .5f;
10         var vx3 = ned + new Vector3(0, 0, width + 1);
11 
12         var vx4 = ned + new Vector3(length + 1, 0, width * .5f + .5f);
13         var vx5 = ned + new Vector3(length + 1, 0, width + 1);
14 
15         var vz2 = ned + new Vector3(length + 1, 0, 0) * .5f;
16         var vz3 = ned + new Vector3(length + 1, 0, 0);
17 
18         var vz4 = ned + new Vector3(length * .5f + .5f, 0, width + 1);
19         var vz5 = ned + new Vector3(length + 1, 0, width + 1);
20 
21         result =
22         //4組射線,每組3條
23         RayCast(ned, Dx, length + 1, S_TAG) ||
24         RayCast(vx2, Dx, length + 1, S_TAG) ||
25         RayCast(vx3, Dx, length + 1, S_TAG) ||
26 
27         RayCast(vx4, Dx * -1, length + 1, S_TAG) ||
28         RayCast(vx5, Dx * -1, length + 1, S_TAG) ||
29         RayCast(vz3, Dx * -1, length + 1, S_TAG) ||
30 
31         RayCast(ned, Dz, width + 1, S_TAG) ||
32         RayCast(vz2, Dz, width + 1, S_TAG) ||
33         RayCast(vz3, Dz, width + 1, S_TAG) ||
34 
35         RayCast(vz4, Dz * -1, width + 1, S_TAG) ||
36         RayCast(vz5, Dz * -1, width + 1, S_TAG) ||
37         RayCast(vx3, Dz * -1, width + 1, S_TAG);
38 
39         return result;
40     }

這裏將射線的起點和終點都延長了一格,是爲了不兩個生成的房間貼得太緊,這樣至少每一個房間與其它房間間隔一個單位格或以上。

 

完整的房間結構生成腳本:

  1 using System.Collections;
  2 using System.Collections.Generic;
  3 using UnityEngine;
  4 using UnityEngine.Events;
  5 
  6 public enum RoomRandType
  7 {
  8     //全隨機
  9     AllRand,
 10     //枚舉大小隨機
 11     EnumRand
 12 }
 13 
 14 public enum RoomShapeType
 15 {
 16     //寬>=長
 17     WidthMain,
 18     //長>=寬
 19     LengthMain,
 20     //自定義,無形狀要求
 21     Coustom
 22 }
 23 //x-length z-width y-height
 24 
 25 public class RoomBuilder : MonoBehaviour
 26 {
 27     //建築單位方塊
 28     public GameObject BuildUnit;
 29 
 30     //房間高度值
 31     public int FixedUnitHeight;
 32     //生成的房間層數
 33     public int LayerCount;
 34     //長寬隨機範圍
 35     public Vector2Int GenRange;
 36 
 37     //隨機類型
 38     public RoomRandType RandType;
 39     //隨機的房間形狀類型
 40     public RoomShapeType Shape;
 41 
 42     //房間大小的隨機列表,用於枚舉隨機
 43     public List<Vector2Int> RoomRandSizes = new List<Vector2Int>();
 44 
 45     //隨機的房間最大面積
 46     public int MaxRoomArea;
 47     //最大隨機數量(隨機試驗次數)
 48     public int MaxRoomCount;
 49 
 50     //最小邊長度
 51     private int MinRoomEdge;
 52     //最大長寬比
 53     public int MaxLengthWidthScale = 2;
 54 
 55     //標準方向
 56     Vector3Int Dx = new Vector3Int(1, 0, 0);
 57     Vector3Int Dy = new Vector3Int(0, 1, 0);
 58     Vector3Int Dz = new Vector3Int(0, 0, 1);
 59 
 60     //建築單位標籤
 61     const string S_TAG = "Unit";
 62 
 63     private MapSystem MapManager;
 64 
 65     void Awake()
 66     {
 67         MapManager = GetComponent<MapSystem>();
 68     }
 69 
 70     public IEnumerator GenRooms(Vector3Int centerPos,UnityAction complete)
 71     {
 72         var temp = (int)Mathf.Sqrt(MaxRoomArea * 1.0f / MaxLengthWidthScale);
 73         MinRoomEdge = temp > 3 ? temp : 3;
 74 
 75         //每層至少1
 76         for (int i = 1; i <= LayerCount; i++)
 77         {
 78             SetGenOneRoom(centerPos, i);
 79             yield return new WaitForSeconds(.1f);
 80         }
 81 
 82         //超過的隨機佈置
 83         var oc = MaxRoomCount - LayerCount;
 84         if (oc > 0)
 85         {
 86             for (int i = 1; i <= oc; i++)
 87             {
 88                 var r = Random.Range(1, LayerCount + 1);
 89                 SetGenOneRoom(centerPos, r);
 90                 yield return new WaitForSeconds(.1f);
 91             }
 92         }
 93 
 94         //全部房間生成完成後發送一個委託信號,以便後續建立房間數據和計算必要鏈接
 95         complete();
 96     }
 97 
 98     void SetGenOneRoom(Vector3Int cp, int r)
 99     {
100         var layerCenter = cp - new Vector3(0, (LayerCount - 2 * r + 1) * .5f * FixedUnitHeight, 0);
101 
102         var rt = RanRoomTran(layerCenter);
103         if (rt != null)
104         {
105             var roomCenter = new Vector3(rt.CenterPos.x, rt.PosY, rt.CenterPos.y);
106 
107             GameObject temp = new GameObject(r.ToString());
108             temp.transform.position = roomCenter;
109             temp.tag = S_TAG;
110 
111             //給生成的房間添加碰撞盒子並設置大小
112             GenOneRoom(roomCenter, rt.Length, rt.Width, temp.transform);
113             var bc = temp.AddComponent<BoxCollider>();
114             bc.size = new Vector3(rt.Length, FixedUnitHeight, rt.Width);
115 
116             //目前用物理方式彷佛難以推開重疊的房間,多是哪裏使用方法有誤,改成用用射線檢測解決...
117             //var rb = temp.AddComponent<Rigidbody>();
118             //rb.useGravity = false;
119             //rb.drag = Mathf.Infinity;
120             //rb.constraints = RigidbodyConstraints.FreezePositionY;
121             //rb.freezeRotation = true;
122 
123             //將房間數據存入臨時列表
124             MapManager.GenRooms.Add(rt);
125             MapManager.UnCrossRooms.Add(rt);
126         }
127     }
128 
129     RoomTran RanRoomTran(Vector3 centerPos)
130     {
131         var rt = new RoomTran();
132 
133         switch (RandType)
134         {
135             case RoomRandType.AllRand:
136                 int temp;
137                 var oe = MaxRoomArea / MinRoomEdge;
138                 switch (Shape)
139                 {
140                     case RoomShapeType.LengthMain:
141                         rt.Length = Random.Range(MinRoomEdge + 1, oe + 1);
142                         temp = MaxRoomArea / rt.Length;
143                         if (temp >= rt.Length)
144                             rt.Width = Random.Range(MinRoomEdge, rt.Length);
145                         else
146                             rt.Width = Random.Range(MinRoomEdge, temp + 1);
147                         break;
148                     case RoomShapeType.WidthMain:
149                         rt.Width = Random.Range(MinRoomEdge + 1, oe + 1);
150                         temp = MaxRoomArea / rt.Width;
151                         if (temp >= rt.Width)
152                             rt.Length = Random.Range(MinRoomEdge, rt.Width);
153                         else
154                             rt.Length = Random.Range(MinRoomEdge, temp + 1);
155                         break;
156                     case RoomShapeType.Coustom:
157                         rt.Length = Random.Range(MinRoomEdge, oe + 1);
158                         temp = MaxRoomArea / rt.Length;
159                         rt.Width = Random.Range(MinRoomEdge, temp + 1);
160                         break;
161                 }
162                 break;
163             case RoomRandType.EnumRand:
164                 var rc = RoomRandSizes.Count;
165                 if (rc == 0)
166                 {
167                     //未填寫時設定隨機默認值
168                     rt.Length = 3;
169                     rt.Width = 3;
170                 }
171                 else
172                 {
173                     var ridx = Random.Range(0,rc);
174                     var t = RoomRandSizes[ridx];
175                     if (t.x < 3 || t.y < 3)
176                     {
177                         //填寫錯誤時設定隨機默認值
178                         rt.Length = 3;
179                         rt.Width = 3;
180                     }
181                     else
182                     {
183                         switch (Shape)
184                         {
185                             case RoomShapeType.LengthMain:
186                                 rt.Length = t.x > t.y ? t.x : t.y;
187                                 rt.Width = t.x < t.y ? t.x : t.y;
188                                 break;
189                             case RoomShapeType.WidthMain:
190                                 rt.Width = t.x > t.y ? t.x : t.y;
191                                 rt.Length = t.x < t.y ? t.x : t.y;
192                                 break;
193                             case RoomShapeType.Coustom:
194                                 rt.Length = Random.value < .5f ? t.x : t.y;
195                                 rt.Width = t.y == rt.Length ? t.x : t.y;
196                                 break;
197                         }         
198                     }
199                 }
200                 break;
201         }
202    
203         rt.CenterPos = new Vector2Int(Random.Range((int)(centerPos.x - GenRange.x * .5f), (int)(centerPos.x + GenRange.x * .5f)),
204             Random.Range((int)(centerPos.z - GenRange.y * .5f), (int)(centerPos.z + GenRange.y * .5f)));
205 
206         rt.PosY = centerPos.y;
207 
208         var roomCenter = new Vector3(rt.CenterPos.x, rt.PosY, rt.CenterPos.y);
209 
210         //射線檢測重疊
211         if (RayRoomCheck(roomCenter, rt.Length, rt.Width))
212         {
213             return null;
214         }
215         return rt;
216     }
217 
218     //生成房間前射線檢測下範圍內有無其餘房間
219     bool RayRoomCheck(Vector3 cp, int length, int width)
220     {
221         bool result = false;
222         //長寬至少留一格間隙,高度與地板格對齊
223         var to = new Vector3(length + 1, FixedUnitHeight - 1, width + 1) * .5f;
224         var ned = cp - to;
225 
226         var vx2 = ned + new Vector3(0, 0, width + 1) * .5f;
227         var vx3 = ned + new Vector3(0, 0, width + 1);
228 
229         var vx4 = ned + new Vector3(length + 1, 0, width * .5f + .5f);
230         var vx5 = ned + new Vector3(length + 1, 0, width + 1);
231 
232         var vz2 = ned + new Vector3(length + 1, 0, 0) * .5f;
233         var vz3 = ned + new Vector3(length + 1, 0, 0);
234 
235         var vz4 = ned + new Vector3(length * .5f + .5f, 0, width + 1);
236         var vz5 = ned + new Vector3(length + 1, 0, width + 1);
237 
238         result =
239         //4組射線,每組3條
240         RayCast(ned, Dx, length + 1, S_TAG) ||
241         RayCast(vx2, Dx, length + 1, S_TAG) ||
242         RayCast(vx3, Dx, length + 1, S_TAG) ||
243 
244         RayCast(vx4, Dx * -1, length + 1, S_TAG) ||
245         RayCast(vx5, Dx * -1, length + 1, S_TAG) ||
246         RayCast(vz3, Dx * -1, length + 1, S_TAG) ||
247 
248         RayCast(ned, Dz, width + 1, S_TAG) ||
249         RayCast(vz2, Dz, width + 1, S_TAG) ||
250         RayCast(vz3, Dz, width + 1, S_TAG) ||
251 
252         RayCast(vz4, Dz * -1, width + 1, S_TAG) ||
253         RayCast(vz5, Dz * -1, width + 1, S_TAG) ||
254         RayCast(vx3, Dz * -1, width + 1, S_TAG);
255 
256         return result;
257     }
258 
259     bool RayCast(Vector3 ori, Vector3 dir, float mD, string tag)
260     {
261         Ray ray = new Ray(ori, dir);
262         RaycastHit info;
263         if (Physics.Raycast(ray, out info, mD))
264         {
265             if (info.transform.tag == tag)
266                 return true;
267         }
268         return false;
269     }
270 
271     /// <summary>
272     /// 生成單一房間的輪廓
273     /// </summary>
274     /// <param name="centerPos">房間中點位置</param>
275     /// <param name="length"></param>
276     /// <param name="width"></param>
277     /// <param name="parent">父物體</param>
278     void GenOneRoom(Vector3 centerPos, int length, int width, Transform parent = null)
279     {
280         var to = new Vector3(length - 1, FixedUnitHeight - 1, width - 1) * .5f;
281 
282         //頂點
283         var ned = centerPos - to;
284         var fod = centerPos + to;
285 
286         var v3 = new Vector3(ned.x, fod.y, ned.z);
287         var v4 = new Vector3(ned.x, fod.y, fod.z);
288         var v5 = new Vector3(ned.x, ned.y, fod.z);
289 
290         var v6 = new Vector3(fod.x, ned.y, ned.z);
291         var v7 = new Vector3(fod.x, ned.y, fod.z);
292         var v8 = new Vector3(fod.x, fod.y, ned.z);
293 
294         //頂點位置(8個)
295         InsSetPos(ned, parent);
296         InsSetPos(fod, parent);
297         InsSetPos(v3, parent);
298         InsSetPos(v4, parent);
299         InsSetPos(v5, parent);
300         InsSetPos(v6, parent);
301         InsSetPos(v7, parent);
302         InsSetPos(v8, parent);
303 
304         //12條棱(4*3)
305         //
306         InsOneEdge(length, ned, Dx, parent);
307         InsOneEdge(length, v3, Dx, parent);
308         InsOneEdge(length, v4, Dx, parent);
309         InsOneEdge(length, v5, Dx, parent);
310         //
311         InsOneEdge(FixedUnitHeight, ned, Dy, parent);
312         InsOneEdge(FixedUnitHeight, v5, Dy, parent);
313         InsOneEdge(FixedUnitHeight, v6, Dy, parent);
314         InsOneEdge(FixedUnitHeight, v7, Dy, parent);
315         //
316         InsOneEdge(width, ned, Dz, parent);
317         InsOneEdge(width, v3, Dz, parent);
318         InsOneEdge(width, v6, Dz, parent);
319         InsOneEdge(width, v8, Dz, parent);
320     }
321 
322     //生成一條邊上的建築單位但不包含頂點位置
323     void InsOneEdge(int edge, Vector3 v, Vector3 dir, Transform parent = null)
324     {
325         //忽略首尾單位
326         for (int i = 1; i < edge - 1; i++)
327         {
328             InsSetPos(v + i * dir, parent);
329         }
330     }
331 
332     void InsSetPos(Vector3 pos, Transform parent = null)
333     {
334         var ins = Instantiate(BuildUnit);
335         ins.transform.position = pos;
336         ins.transform.parent = parent;
337     }
338 }

 

在MapSystem中能夠在房間結構生成完後建立一個默認的數據結構:

 1     public void RandRoomDatas()
 2     {
 3         if (RoomBuilder == null||MapData ==null)
 4             return;
 5 
 6         RoomBuilder.StartCoroutine(RoomBuilder.GenRooms(MapData.MapCenter,()=> 
 7         {
 8             CreatRoomData();
 9             RandRoomCrosses();
10         }));
11     }
12 
13     void CreatRoomData()
14     {
15         for (int i = 1; i < GenRooms.Count + 1; i++)
16         {
17             var rd = new RoomData();
18             rd.Id = i;
19             rd.RoomTran = GenRooms[i - 1];
20             rd.BattleType = RoomBattleType.NormalBattle;
21             if (rd.Id == 1)
22                 rd.BattleType = RoomBattleType.Rest;
23             rd.CrossRooms = new List<RoomData>();
24             rd.Monsters = new List<GameObject>();
25             rd.bEndRoom = false;
26             rd.bMainCrossRoom = false;
27 
28             MapData.RoomDataDic.Add(rd.Id, rd);
29         }
30     }

 

效果圖:(單層-枚舉列表隨機)

 

 單層(全隨機-長條形房間隨機):

 

 多層(層數5)(自定義-全隨機):

 

 參考資料:

https://indienova.com/indie-game-development/rooms-and-mazes-a-procedural-dungeon-generator/?tdsourcetag=s_pctim_aiomsg

https://mp.weixin.qq.com/s/3yM-mAAXq_fX5tcy82s0uQ

相關文章
相關標籤/搜索