整体思路:使用二维数组保存房间位置信息,将二维数组从中心点划分成四个区域,然后随机在对角的两个区域内确定起点和终点。然后生成一条连通起点和终点的路线,再在路线上对地图房间进行扩展。

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MapGenerator : MonoBehaviour
{
float spaceX = 15f;//房间生成区域宽
float spaceY = 9.5f;//房间生成区域高
public GameObject roomPrefab;//房间预制体
public GameObject baseDoorPrefab;//普通门预制体
List<RoomModel> rooms = new List<RoomModel>();
MapUtilities mu = new MapUtilities();
private void Start()
{

List<Vector2> temp = new List<Vector2>();
temp = mu.MapGenerator(5, 5);

for (int i = 0; i < temp.Count; i++)
{
rooms.Add(new RoomModel(temp[i]));
}
//TODO 扩展房间
///1. 遍历并找出对角线上无房间的扩展两层
///2. 对角线上有一个房间扩展一层
///3. 对角线上有两个及以上房间,不进行扩展
/// 地图完全生成后 添加门
IniRooms(rooms);

AddDoor(rooms);
for (int i = 0; i < 8; i++)
{
Debug.Log(rooms[3].neighborState[i]);
}

RoomGenerator(rooms);
}


void IniRooms(List<RoomModel> _rooms)
{
//设定房间偏移
Vector2 temp = _rooms[1].coord;
for (int i = 0; i < _rooms.Count; i++)
{
_rooms[i].coord = _rooms[i].coord - temp;
}
//遍历rooms,初始化room的相邻信息
for (int i = 0; i < _rooms.Count; i++)
{
for (int j = 0; j < _rooms.Count; j++)
{
if ((_rooms[i].coord + new Vector2(-1, 1)) == _rooms[j].coord)
{
_rooms[i].neighborState[0] = true;
}
if ((_rooms[i].coord + new Vector2(0, 1)) == _rooms[j].coord)
{
_rooms[i].neighborState[1] = true;
}
if ((_rooms[i].coord + new Vector2(1, 1)) == _rooms[j].coord)
{
_rooms[i].neighborState[2] = true;
}
if ((_rooms[i].coord + new Vector2(1, 0)) == _rooms[j].coord)
{
_rooms[i].neighborState[3] = true;
}
if ((_rooms[i].coord + new Vector2(1, -1)) == _rooms[j].coord)
{
_rooms[i].neighborState[4] = true;
}
if ((_rooms[i].coord + new Vector2(0, -1)) == _rooms[j].coord)
{
_rooms[i].neighborState[5] = true;
}
if ((_rooms[i].coord + new Vector2(-1, -1)) == _rooms[j].coord)
{
_rooms[i].neighborState[6] = true;
}
if ((_rooms[i].coord + new Vector2(-1, 0)) == _rooms[j].coord)
{
_rooms[i].neighborState[7] = true;
}

}
}


}
void AddDoor(List<RoomModel> _rooms)
{
foreach (var item in _rooms)
{
for (int i = 0; i < item.neighborState.Length; i++)
{
if (item.neighborState[i])
{
if (i == 1)
{
Instantiate(baseDoorPrefab, new Vector3(item.coord.x * spaceX, item.coord.y * spaceY + 3.4f, 0), Quaternion.identity);
}
if (i == 5)
{
Instantiate(baseDoorPrefab, new Vector3(item.coord.x * spaceX, item.coord.y * spaceY - 3.4f, 0), Quaternion.identity).transform.localEulerAngles = new Vector3(0, 0, 180);
}
if (i == 3)
{
Instantiate(baseDoorPrefab, new Vector3(item.coord.x * spaceX + 5.9f, item.coord.y * spaceY, 0), Quaternion.identity).transform.localEulerAngles = new Vector3(0, 0, -90);
}
if (i == 7)
{
Instantiate(baseDoorPrefab, new Vector3(item.coord.x * spaceX - 5.9f, item.coord.y * spaceY, 0), Quaternion.identity).transform.localEulerAngles = new Vector3(0, 0, 90);
}
}

}

}
}
void RoomGenerator(List<RoomModel> _rooms)
{


for (int i = 0; i < _rooms.Count; i++)
{
Instantiate(roomPrefab, new Vector3(_rooms[i].coord.x * spaceX, _rooms[i].coord.y * spaceY, 0), Quaternion.identity);
}
}



}
public class RoomModel
{
public Vector2 coord = new Vector2();//房间坐标
/// <summary>
///房间相邻状态,长度为8,从左上到左下一圈相应index为从0到7
public bool[] neighborState = new bool[8];

public RoomModel(Vector2 coord)
{
this.coord = coord;

}
}

工具类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MapUtilities
{
/// <summary>
/// 根据给定长宽,在矩阵内生成一条连通的随机长度的数组坐标
/// </summary>
/// <param name="maxX">矩阵行</param>
/// <param name="maxY">矩阵列</param>
/// <returns></returns>
public List<Vector2> MapGenerator(int maxX, int maxY)
{


int centaerX = (int)(maxX / 2);
int centaerY = (int)(maxY / 2);


List<Vector2> path = new List<Vector2>();

int startIndex =UnityEngine.Random.Range(0, 4);//0,1,2,3,

//起始点位置
int startX;
int startY;

//终点位置
int endX, endY;

switch (startIndex)
{
case 0:
startX = UnityEngine.Random.Range(0, centaerX);
startY = UnityEngine.Random.Range(0, centaerY);
endX = UnityEngine.Random.Range(centaerX + 1, maxX);
endY = UnityEngine.Random.Range(centaerY + 1, maxY);
break;
case 1:
startX = UnityEngine.Random.Range(0, centaerX);
startY = UnityEngine.Random.Range(centaerY + 1, maxY);

endX = UnityEngine.Random.Range(centaerX + 1, maxX);
endY = UnityEngine.Random.Range(0, centaerY);
break;
case 2:
startX = UnityEngine.Random.Range(centaerX + 1, maxX);
startY = UnityEngine.Random.Range(0, centaerY);

endX = UnityEngine.Random.Range(0, centaerX);
endY = UnityEngine.Random.Range(centaerY + 1, maxY);
break;
case 3:
startX = UnityEngine.Random.Range(centaerX + 1, maxX);
startY = UnityEngine.Random.Range(centaerY + 1, maxY);
endX = UnityEngine.Random.Range(0, centaerX);
endY = UnityEngine.Random.Range(0, centaerY);
break;
default:
startX = UnityEngine.Random.Range(0, centaerX);
startY = UnityEngine.Random.Range(0, centaerY);
endX = UnityEngine.Random.Range(centaerX + 1, maxX);
endY = UnityEngine.Random.Range(centaerY + 1, maxY);
break;
}
path.Add(new Vector2(startY, -startX));
//设置连通路线
int stepX = (int)Mathf.Abs(endX - startX);
int stepY = (int)Mathf.Abs(endY - startY);



int tempX = startX;
int tempY = startY;
// Console.WriteLine(path.Count);
while (path.Count < (stepX + stepY))
{
int direction = UnityEngine.Random.Range(0, 2);
// Console.WriteLine(path.Count);

switch (startIndex)
{
#region 起始位置在左上
case 0:

if (tempX < endX)
{
if (tempY < endY)
{
if (direction == 0)
{
tempX++;
}
else
{
tempY++;
}
}
else
{
tempX++;
}

}
else
{
if (tempY < endY)
{
tempY++;
}

}
break;

#endregion
#region 起始位置在右上
case 1:
if (tempX < endX)
{
if (tempY > endY)
{
if (direction == 0)
{

tempX++;


}
else
{
if (tempY != 0)
{
tempY--;

}
}
}
else
{

tempX++;


}

}
else
{
if (tempY > endY)
{
if (tempY != 0)
{
tempY--;

}
}

}
break;
#endregion
#region 起始位置在左下
case 2:
if (tempX > endX)
{
if (tempY < endY)
{
if (direction == 0)
{
if (tempX != 0)
{
tempX--;
}
}
else
{

tempY++;


}
}
else
{
if (tempX != 0)
{
tempX--;
}
}

}
else
{
if (tempY < endY)
{
tempY++;
}

}
break;

#endregion
#region 起始位置在右下
case 3:
if (tempX > endX)
{
if (tempY > endY)
{
if (direction == 0)
{
if (tempX != 0)
{
tempX--;

}
}
else
{
if (tempY != 0)
{
tempY--;

}
}
}
else
{
if (tempX != 0)
{
tempX--;

}
}

}
else
{
if (tempY > endY)
{
if (tempY != 0)
{
tempY--;

}
}

}

break;
#endregion

default:
if (tempX < endX)
{
if (tempY < endY)
{
if (direction == 0)
{
tempX++;
}
else
{
tempY++;
}
}
else
{
tempX++;
}

}
else
{
if (tempY < endY)
{
tempY++;
}

}
break;
}

path.Add(new Vector2(tempY, -tempX));
// Console.WriteLine(path.Count);
}

// Console.WriteLine("start " + startX + "," + startY);
// Console.WriteLine("end " + endX + "," + endY);
path.Add(new Vector2(endY,-endX));
return path;
}


}