欢迎访问欧博亚洲(Allbet Game)!

首页科技正文

鹤岗租房网:Unity 随机舆图房间通道天生

admin2020-09-1160

之前的博客中已经说了随机房间天生:

https://www.cnblogs.com/koshio0219/p/12604383.html

但实现房间天生只是整个舆图天生最初最简朴的一步。下面讨论若何随机天生毗邻房间的通道。

 

房间的通道一样平常要知足以下特征和特征:

1.保证所有随机天生的房间都可以通过通道从起点到达终点,不泛起未毗邻或毗邻中止的情形。

2.通道在天生的历程中不能穿过房间内部。

3.思量是简练直接的毗邻方式,照样更为曲折的通道。

 

现在,眼前泛起了许多随机天生的房间,那么问题是:到底哪两个房间需要毗邻一条通道呢,若是以最快的速率得出所有需要毗邻的通道列表呢?

这时,我们先不用将空间中天生的这些房间仅仅当前是房间来看待,实质上它们就是漫衍在空间中的一些点的聚集,每一个点都能求出当前离它们最近的点是哪一个,

那么一个异常简朴的算法是,我们可以纪录两个列表:已经处于毗邻状态的点的列表(闭合列表),尚未取得毗邻的点的列表(开放列表)。

先随机一个点作为起点,毗邻离该起点最近的点,将起点和改点置入闭合列表中,再以第二个点作为起点毗邻最近的点,以此方式不停循环,直至所有的开放列表清空,所有通道的毗邻数据即所有盘算完毕。

上面这样虽然可以很快得出所有毗邻的通道列表,但缺乏毗邻的随机性,也无法发生分支路径,游戏性很低。

因此,可以思量给每个毗邻的点增添分外分支的概率,这样每个点就至少需要盘算与它最近的两个点的位置,在概率的控制下其中一个作为主要路径链表中的值,另一个不毗邻或毗邻为分支置入闭合列表中。

天生之后的房间数据结构最终会是一个二叉树。

 

主要属性:

 1     public bool bDebug = false;
 2     public MapData MapData;
 3     public RoomBuilder RoomBuilder;
 4     public CrossBuilder CrossBuilder;
 5 
 6     //所有天生的房间列表
 7     public List<RoomTran> GenRooms = new List<RoomTran>();
 8     //当前未毗邻房间列表
 9     public List<RoomTran> UnCrossRooms = new List<RoomTran>();
10 
11     private RoomTran FirstRoom;
12     private RoomTran LastRoom;
13 
14     //分外路径概率
15     public float AnotherCrossProbability = .2f;
16     //死路概率
17     public float DeadCrossProbability = .5f;
18     //死路延伸概率
19     public float DeadAwayProbability = .6f;
20 
21     //死路房间节点列表(盘算时清扫)
22     List<RoomTran> DeadRooms = new List<RoomTran>();
23     //每个房间毗邻其他房间的字典
24     Dictionary<RoomTran, List<RoomTran>> RoomCrossRooms = new Dictionary<RoomTran, List<RoomTran>>();
25     //主通路
26     public LinkedList<RoomTran> MainCross = new LinkedList<RoomTran>();
27 
28     //竣事断点列表
29     List<RoomTran> EndRooms = new List<RoomTran>();
30 
31     [HideInInspector]
32     public  List<GameObject> CrossUnitInsts = new List<GameObject>();
33     [HideInInspector]
34     public List<GameObject> RoomUnitInsts = new List<GameObject>();

 

舆图数据结构:

 1 using System.Collections.Generic;
 2 using UnityEngine;
 3 
 4 public class MapData : MonoBehaviour
 5 {
 6     public Vector3Int MapCenter;
 7 
 8     public Dictionary<int, RoomData> RoomDataDic = new Dictionary<int, RoomData>();
 9 
10     public List<CrossData> CrossDataList = new List<CrossData>();
11 
12     public Dictionary<int, List<int>> RoomCrossRoomsDic = new Dictionary<int, List<int>>();
13 
14     public List<Vector3> CrossUnitPos = new List<Vector3>();
15 }
16 
17 public struct CrossData
18 {
19     public int id1;
20     public int id2;
21 }


焦点盘算函数:

 1     void CalNextCross(RoomTran nr, RoomTran br = null)
 2     {
 3         MainCross.AddLast(nr);
 4         LRemove(UnCrossRooms, nr);
 5 
 6         var fcl = FindLatelyRooms(nr);
 7 
 8         if (fcl.FirstLately != null)
 9         {
10             if (fcl.SecondLately != null)
11             {
12                 if (Random.value < AnotherCrossProbability)
13                 {
14                     if (Random.value < DeadCrossProbability)
15                     {
16                         var dr = Random.value < .5f ? fcl.FirstLately : fcl.SecondLately;
17                         var lr = dr == fcl.FirstLately ? fcl.SecondLately : fcl.FirstLately;
18 
19                         LAdd(DeadRooms, dr);
20 
21                         AddItemToRoomDic(nr, lr, dr, br);
22                         LRemove(UnCrossRooms, dr);
23                         LRemove(UnCrossRooms, lr);
24 
25                         CalDeadCross(dr, nr);
26                         CalNextCross(lr, nr);
27                     }
28                     else
29                     {
30                         var mr = Random.value < .5f ? fcl.FirstLately : fcl.SecondLately;
31                         var or = mr == fcl.FirstLately ? fcl.SecondLately : fcl.FirstLately;
32                         AddItemToRoomDic(or, nr);
33                         AddItemToRoomDic(nr, mr, or, br);
34                         CalNextCross(mr, nr);
35                     }
36                 }
37                 else
38                 {
39                     AddItemToRoomDic(nr, br, fcl.FirstLately);
40                     CalNextCross(fcl.FirstLately, nr);
41                 }
42             }
43             else
44             {
45                 AddItemToRoomDic(nr, br, fcl.FirstLately);
46                 CalNextCross(fcl.FirstLately, nr);
47             }
48         }
49         else
50         {
51             //盘算竣事
52             LastRoom = nr;
53             AddItemToRoomDic(nr, br);
54             LAdd(EndRooms, nr);
55 
56             Debug.Log("天生房间数:" + GenRooms.Count);
57             Debug.Log("主路径房间数:" + MainCross.Count);
58             Debug.Log("分支房间数:" + DeadRooms.Count);
59             Debug.Log("端点房间数:" + EndRooms.Count);
60 
61             //更新舆图数据
62             UpdateMapData();
63             //按顺序执行现实毗邻
64             CrossBuilder.StartCoroutine(CrossBuilder.GenCrosses());
65         }
66     }

 

完整的MapSystem剧本:

  1 using System.Collections.Generic;
  2 using UnityEngine;
  3 
  4 //这个剧本找出哪些房间之间需要相互毗邻通道
  5 public class MapSystem : MonoBehaviour
  6 {
  7     public bool bDebug = false;
  8     public MapData MapData;
  9     public RoomBuilder RoomBuilder;
 10     public CrossBuilder CrossBuilder;
 11 
 12     //所有天生的房间列表
 13     public List<RoomTran> GenRooms = new List<RoomTran>();
 14     //当前未毗邻房间列表
 15     public List<RoomTran> UnCrossRooms = new List<RoomTran>();
 16 
 17     private RoomTran FirstRoom;
 18     private RoomTran LastRoom;
 19 
 20     //分外路径概率
 21     public float AnotherCrossProbability = .2f;
 22     //死路概率
 23     public float DeadCrossProbability = .5f;
 24     //死路延伸概率
 25     public float DeadAwayProbability = .6f;
 26 
 27     //死路房间节点列表(盘算时清扫)
 28     List<RoomTran> DeadRooms = new List<RoomTran>();
 29     //每个房间毗邻其他房间的字典
 30     Dictionary<RoomTran, List<RoomTran>> RoomCrossRooms = new Dictionary<RoomTran, List<RoomTran>>();
 31     //主通路
 32     public LinkedList<RoomTran> MainCross = new LinkedList<RoomTran>();
 33 
 34     //竣事断点列表
 35     List<RoomTran> EndRooms = new List<RoomTran>();
 36 
 37     [HideInInspector]
 38     public  List<GameObject> CrossUnitInsts = new List<GameObject>();
 39     [HideInInspector]
 40     public List<GameObject> RoomUnitInsts = new List<GameObject>();
 41 
 42     //修建单元标签
 43     public const string S_TAG = "Unit";
 44 
 45     [HideInInspector]
 46     public bool bAction = false;
 47 
 48     public void Start()
 49     {
 50         CrossBuilder = GetComponent<CrossBuilder>();
 51         RoomBuilder = GetComponent<RoomBuilder>();
 52     }
 53 
 54     void SetSeed(bool bDebug)
 55     {
 56         int seed;
 57         if (bDebug)
 58         {
 59             seed = PlayerPrefs.GetInt("Seed");
 60 
 61         }
 62         else
 63         {
 64             seed = (int)System.DateTime.Now.Ticks;
 65             PlayerPrefs.SetInt("Seed", seed);
 66         }
 67         Random.InitState(seed);
 68     }
 69 
 70     public void RandRoomDatas()
 71     {
 72         if (RoomBuilder == null || MapData == null)
 73             return;
 74 
 75         bAction = true;
 76         SetSeed(bDebug);
 77         RoomBuilder.StartCoroutine(RoomBuilder.GenRooms(MapData.MapCenter, () =>
 78          {
 79              CreatRoomData();
 80              RandRoomCrosses();
 81          }));
 82     }
 83 
 84     public void RandRoomCrosses()
 85     {
 86         if (GenRooms.Count <= 0) return;
 87 
 88         FirstRoom = GenRooms[Random.Range(0, GenRooms.Count)];
 89 
 90         CalNextCross(FirstRoom);
 91     }
 92 
 93     void UpdateMapData()
 94     {
 95         foreach (var rd in MapData.RoomDataDic)
 96         {
 97             var rt = rd.Value.RoomTran;
 98             if (RoomCrossRooms.ContainsKey(rt))
 99             {
100                 var temp = new List<int>();
101                 foreach (var crt in RoomCrossRooms[rt])
102                 {
103                     var id = GetRoomIdByRT(crt);
104                     if (id > 0)
105                     {
106                         temp.Add(id);
107 
108                         rd.Value.CrossRooms.Add(MapData.RoomDataDic[id]);
109 
110                         var cd = new CrossData();
111                         cd.id1 = rd.Key;
112                         cd.id2 = id;
113                         if (!CrossDataContains(cd))
114                             MapData.CrossDataList.Add(cd);
115                     }
116                 }
117                 MapData.RoomCrossRoomsDic.Add(rd.Key, temp);
118             }
119 
120             if (MainCross.Contains(rt))
121             {
122                 rd.Value.bMainCrossRoom = true;
123                 if (EndRooms.Contains(rt))
124                 {
125                     rd.Value.BattleType = RoomBattleType.BossBattle;
126                 }
127             }
128 
129             if (EndRooms.Contains(rt))
130             {
131                 rd.Value.bEndRoom = true;
132             }
133         }
134     }
135 
136     bool CrossDataContains(CrossData d)
137     {
138         foreach (var cd in MapData.CrossDataList)
139         {
140             if ((cd.id1 == d.id1 && cd.id2 == d.id2) || (cd.id1 == d.id2 && cd.id2 == d.id1))
141                 return true;
142         }
143         return false;
144     }
145 
146     int GetRoomIdByRT(RoomTran rt)
147     {
148         foreach (var rd in MapData.RoomDataDic)
149         {
150             if (rd.Value.RoomTran == rt)
151                 return rd.Key;
152         }
153         return -1;
154     }
155 
156     void CreatRoomData()
157     {
158         for (int i = 1; i < GenRooms.Count + 1; i++)
159         {
160             var rd = new RoomData();
161             rd.Id = i;
162             rd.RoomTran = GenRooms[i - 1];
163             rd.BattleType = RoomBattleType.NormalBattle;
164             if (rd.Id == 1)
165                 rd.BattleType = RoomBattleType.Rest;
166             rd.CrossRooms = new List<RoomData>();
167             rd.Monsters = new List<GameObject>();
168             rd.bEndRoom = false;
169             rd.bMainCrossRoom = false;
170 
171             MapData.RoomDataDic.Add(rd.Id, rd);
172         }
173     }
174 
175     void CalNextCross(RoomTran nr, RoomTran br = null)
176     {
177         MainCross.AddLast(nr);
178         LRemove(UnCrossRooms, nr);
179 
180         var fcl = FindLatelyRooms(nr);
181 
182         if (fcl.FirstLately != null)
183         {
184             if (fcl.SecondLately != null)
185             {
186                 if (Random.value < AnotherCrossProbability)
187                 {
188                     if (Random.value < DeadCrossProbability)
189                     {
190                         var dr = Random.value < .5f ? fcl.FirstLately : fcl.SecondLately;
191                         var lr = dr == fcl.FirstLately ? fcl.SecondLately : fcl.FirstLately;
192 
193                         LAdd(DeadRooms, dr);
194 
195                         AddItemToRoomDic(nr, lr, dr, br);
196                         LRemove(UnCrossRooms, dr);
197                         LRemove(UnCrossRooms, lr);
198 
199                         CalDeadCross(dr, nr);
200                         CalNextCross(lr, nr);
201                     }
202                     else
203                     {
204                         var mr = Random.value < .5f ? fcl.FirstLately : fcl.SecondLately;
205                         var or = mr == fcl.FirstLately ? fcl.SecondLately : fcl.FirstLately;
206                         AddItemToRoomDic(or, nr);
207                         AddItemToRoomDic(nr, mr, or, br);
208                         CalNextCross(mr, nr);
209                     }
210                 }
211                 else
212                 {
213                     AddItemToRoomDic(nr, br, fcl.FirstLately);
214                     CalNextCross(fcl.FirstLately, nr);
215                 }
216             }
217             else
218             {
219                 AddItemToRoomDic(nr, br, fcl.FirstLately);
220                 CalNextCross(fcl.FirstLately, nr);
221             }
222         }
223         else
224         {
225             //盘算竣事
226             LastRoom = nr;
227             AddItemToRoomDic(nr, br);
228             LAdd(EndRooms, nr);
229 
230             Debug.Log("天生房间数:" + GenRooms.Count);
231             Debug.Log("主路径房间数:" + MainCross.Count);
232             Debug.Log("分支房间数:" + DeadRooms.Count);
233             Debug.Log("端点房间数:" + EndRooms.Count);
234 
235             //更新舆图数据
236             UpdateMapData();
237             //按顺序执行现实毗邻
238             CrossBuilder.StartCoroutine(CrossBuilder.GenCrosses());
239         }
240     }
241 
242     CrossLately FindLatelyRooms(RoomTran tar)
243     {
244         var cl = new CrossLately();
245         float firstSqrdis = Mathf.Infinity;
246         float secondSqrdis = Mathf.Infinity;
247 
248         foreach (var room in UnCrossRooms)
249         {
250             var rc = new Vector3(room.CenterPos.x, room.PosY, room.CenterPos.y);
251             var tc = new Vector3(tar.CenterPos.x, tar.PosY, tar.CenterPos.y);
252             float sqrdis = (rc - tc).sqrMagnitude;
253 
254             if (sqrdis < firstSqrdis)
255             {
256                 firstSqrdis = sqrdis;
257                 cl.FirstLately = room;
258             }
259             else if (sqrdis < secondSqrdis)
260             {
261                 secondSqrdis = sqrdis;
262                 cl.SecondLately = room;
263             }
264         }
265         return cl;
266     }
267 
268     //盘算死路,此处死路没有分支
269     void CalDeadCross(RoomTran fdr, RoomTran bdr)
270     {
271         var temp = FindLatelyRooms(fdr);
272         if (temp.FirstLately != null && Random.value < DeadAwayProbability)
273         {
274             LRemove(UnCrossRooms, temp.FirstLately);
275             LAdd(DeadRooms, temp.FirstLately);
276             AddItemToRoomDic(fdr, temp.FirstLately, bdr);
277             CalDeadCross(temp.FirstLately, fdr);
278         }
279         else
280         {
281             //彻底殒命
282             LRemove(UnCrossRooms, fdr);
283             LAdd(DeadRooms, fdr);
284             AddItemToRoomDic(fdr, bdr);
285             LAdd(EndRooms, fdr);
286         }
287     }
288 
289     void LRemove<T>(List<T> list, T item)
290     {
291         if (list.Contains(item))
292         {
293             list.Remove(item);
294         }
295     }
296 
297     void LAdd<T>(List<T> list, T item)
298     {
299         if (!list.Contains(item))
300         {
301             list.Add(item);
302         }
303     }
304 
305     void AddItemToRoomDic(RoomTran key, RoomTran item1, RoomTran item2 = null, RoomTran item3 = null)
306     {
307         if (RoomCrossRooms.ContainsKey(key))
308         {
309             if (item1 != null)
310                 if (!RoomCrossRooms[key].Contains(item1))
311                     RoomCrossRooms[key].Add(item1);
312             if (item2 != null)
313                 if (!RoomCrossRooms[key].Contains(item2))
314                     RoomCrossRooms[key].Add(item2);
315             if (item3 != null)
316                 if (!RoomCrossRooms[key].Contains(item3))
317                     RoomCrossRooms[key].Add(item3);
318         }
319         else
320         {
321             RoomCrossRooms.Add(key, new List<RoomTran>());
322             AddItemToRoomDic(key, item1, item2, item3);
323         }
324     }
325 
326     public bool RayCast(Vector3 ori, Vector3 dir, float mD)
327     {
328         Ray ray = new Ray(ori, dir);
329         RaycastHit info;
330         if (Physics.Raycast(ray, out info, mD))
331         {
332             if (info.transform.tag == S_TAG)
333                 return true;
334         }
335         return false;
336     }
337 
338     public GameObject InsSetPos(GameObject prefab,Vector3 pos, Transform parent = null)
339     {
340         var ins = Instantiate(prefab);
341         ins.transform.position = pos;
342         ins.transform.parent = parent;
343         return ins;
344     }
345 
346     public RoomTran GetRoomByPos(Vector3 pos)
347     {
348         foreach (var room in GenRooms)
349         {
350             var to = new Vector3(room.Length, RoomBuilder.FixedUnitHeight, room.Width) * .5f;
351 
352             var centerPos = new Vector3(room.CenterPos.x, room.PosY, room.CenterPos.y);
353             var ned = centerPos - to;
354             var fod = centerPos + to;
355 
356             if (pos.x >= ned.x && pos.x <= fod.x && pos.y >= ned.y && pos.y <= fod.y && pos.z >= ned.z && pos.z <= fod.z)
357             {
358                 return room;
359             }
360         }
361         return null;
362     }
363 
364     public ExCross GetExCross(Vector3 strPos, Vector3 tarPos)
365     {
366         var ec = new ExCross();
367         var rt = GetRoomByPos(strPos);
368         if (rt != null)
369         {
370             var to = new Vector3(rt.Length - 1, RoomBuilder.FixedUnitHeight - 1, rt.Width - 1) * .5f;
371 
372             var centerPos = new Vector3(rt.CenterPos.x, rt.PosY, rt.CenterPos.y);
373             var ned = centerPos - to;
374             var fod = centerPos + to;
375             if (strPos.x == tarPos.x)
376             {
377                 if (Random.value < .5f)
378                 {
379                     ec.pos1 = strPos.z < tarPos.z ? new Vector3(ned.x - 1, strPos.y, strPos.z - 1) : new Vector3(ned.x - 1, strPos.y, strPos.z + 1);
380                     ec.pos2 = strPos.z < tarPos.z ? ec.pos1 + new Vector3(0, 0, rt.Width + 1) : ec.pos1 - new Vector3(0, 0, rt.Width + 1);
381                     ec.pos3 = new Vector3(strPos.x, strPos.y, ec.pos2.z);
382                 }
383                 else
384                 {
385                     ec.pos1 = strPos.z < tarPos.z ? new Vector3(fod.x + 1, strPos.y, strPos.z - 1) : new Vector3(fod.x + 1, strPos.y, strPos.z + 1);
386                     ec.pos2 = strPos.z < tarPos.z ? ec.pos1 + new Vector3(0, 0, rt.Width + 1) : ec.pos1 - new Vector3(0, 0, rt.Width + 1);
387                     ec.pos3 = new Vector3(strPos.x, strPos.y, ec.pos2.z);
388                 }
389 
390             }
391             else if (strPos.z == tarPos.z)
392             {
393                 if (Random.value < .5f)
394                 {
395                     ec.pos1 = strPos.x < tarPos.x ? new Vector3(strPos.x - 1, strPos.y, ned.z - 1) : new Vector3(strPos.x + 1, strPos.y, ned.z - 1);
396                     ec.pos2 = strPos.x < tarPos.x ? ec.pos1 + new Vector3(rt.Length + 1, 0, 0) : ec.pos1 - new Vector3(rt.Length + 1, 0, 0);
397                     ec.pos3 = new Vector3(ec.pos2.x, strPos.y, strPos.z);
398                 }
399                 else
400                 {
401                     ec.pos1 = strPos.x < tarPos.x ? new Vector3(strPos.x - 1, strPos.y, fod.z + 1) : new Vector3(strPos.x + 1, strPos.y, fod.z + 1);
402                     ec.pos2 = strPos.x < tarPos.x ? ec.pos1 + new Vector3(rt.Length + 1, 0, 0) : ec.pos1 - new Vector3(rt.Length + 1, 0, 0);
403                     ec.pos3 = new Vector3(ec.pos2.x, strPos.y, strPos.z);
404                 }
405             }
406         }
407         return ec;
408     }
409 
410     public void OnClickReset()
411     {
412         if (bAction)
413             return;
414 
415         if (CrossUnitInsts.Count == 0 && RoomUnitInsts.Count == 0)
416             return;
417         
418         for(int i = 0; i < CrossUnitInsts.Count; i++)
419         {
420             Destroy(CrossUnitInsts[i]);
421         }
422 
423         for (int i = 0; i < RoomUnitInsts.Count; i++)
424         {
425             Destroy(RoomUnitInsts[i]);
426         }
427 
428         ClearAll();
429         RandRoomDatas();
430     }
431 
432     public void ClearAll()
433     {
434         GenRooms.Clear();
435         UnCrossRooms.Clear();
436         DeadRooms.Clear();
437         EndRooms.Clear();
438         MainCross.Clear();
439         RoomCrossRooms.Clear();
440         RoomUnitInsts.Clear();
441         CrossUnitInsts.Clear();
442 
443         MapData.RoomDataDic.Clear();
444         MapData.RoomCrossRoomsDic.Clear();
445         MapData.CrossDataList.Clear();
446         MapData.CrossUnitPos.Clear();
447     }
448 }
449 
450 public struct CrossLately
451 {
452     public RoomTran FirstLately;
453     public RoomTran SecondLately;
454 }
455 
456 public struct ExCross
457 {
458     public Vector3 pos1;
459     public Vector3 pos2;
460     public Vector3 pos3;
461 }
View Code

 

在盘算完所有的房间毗邻通路后,更新舆图数据,随后再凭据舆图数据中的通路情形举行现实通路毗邻。

现实毗邻的历程中许多都是数学问题,需要单独剖析两个房间的位置关系,基本剖析模式如下:

1.两个房间是否位于统一层,若是不是,是否有重叠区域

(通过剖析边缘坐标的极限值来判断交叠情形,例如当其中一个房间随便一个轴向的最小值大于目的房间对应轴向的最大值或该轴向的最大值小于目的房间轴向的最小值时,以为两个房间有重叠的轴向区域,否则在该轴向上无重叠)

2.若是两个房间位于统一层,或原本就只天生单层的舆图,思量这两个房间是否共边,共边和不共边的毗邻方式是有区别的

3.思量在毗邻的历程中遭遇其他房间或障碍物时若何处置,是绕过障碍物前进照样断开毗邻,若何绕开障碍物

 

最简朴的就是共边的情形:

 

这时可以选择共边局限内的随便一条直线作为毗邻方式(上图绿色区域),这是注重临界值得点应该清扫在外(由于现实情形下房间由于有墙壁的厚度,最外边的一格巨细是没办法形成通路的)

判断共边与否的方式就是盘算临界值:

1     Vector2 CheckCommonSide(float axis1, int edge1, float axis2, int edge2)
2     {
3         var max1 = axis1 + (edge1 - 1) * .5f - 1;
4         var min1 = axis1 - (edge1 - 1) * .5f + 1;
5         var max2 = axis2 + (edge2 - 1) * .5f - 1;
6         var min2 = axis2 - (edge2 - 1) * .5f + 1;
7 
8         return new Vector2(max1 > max2 ? max2 : max1, min1 > min2 ? min1 : min2);
9     }

若是返回的值中y>x,则对应轴向不共边(这里之所以给边的长度盘算时-1思量房间的墙壁厚度单元)

 

第二种情形,不共边但在统一层:

鹤岗租房网:Unity 随机舆图房间通道天生 第1张

 

这时就会有两种靠近最短门路的折线毗邻方式,首先我们依然需要找出两个房间最靠近的那四个临界值的点,在判断出无共边区域后选取其中一对坐标举行L形折线毗邻,L形的折线毗邻实质上就是两段直线毗邻,只不过增添了一个中心点。

但上面的思量有时是过于理想的情形,事实上在随机天生的房间中很容易泛起毗邻路径被其他房间阻挡的情形,最直接的处置方式显然是直接断开,横竖通过断开的房间通路过渡也是可以到达目的的,但下面要思量的是若何绕过目的的做法,

具体来说也分为两种情形:

1.一段直线历程中有其他房间,这样可以思量直接取得障碍房间左侧或右侧的两个点举行过渡:

 1     void CrossAround(Vector3 pos, Vector3 max, ExCross cps)
 2     {
 3         if (cps.pos1 != Vector3.zero && cps.pos2 != Vector3.zero && cps.pos3 != Vector3.zero)
 4         {
 5             LineTwoPos(pos, cps.pos1);
 6             LineTwoPos(cps.pos1, cps.pos2);
 7             LineTwoPos(cps.pos2, cps.pos3);
 8             LineTwoPos(cps.pos3, max);
 9         }
10     }

下面这种情形稍微庞大一点,就是:

2.折线的中点在障碍物房间内,这时,简朴的直线绕道是不可取的

鹤岗租房网:Unity 随机舆图房间通道天生 第2张

 

需要盘算障碍物房间四个角中最合适的一个边缘角举行过渡:

 1     void LShapePos(Vector3 pos1, Vector3 pos2, Vector3 cp)
 2     {
 3         //判断折线中心点是否位于其他房间内,若位于,则需要重新寻路
 4         var rt = MapSystem.GetRoomByPos(cp);
 5         if (ObstacleCrossType == ObstacleCrossType.Detour && rt != null)
 6         {
 7             var to = new Vector2(rt.Length + 1, rt.Width + 1) * .5f;
 8 
 9             var ned = rt.CenterPos - to;
10             var fod = rt.CenterPos + to;
11 
12             Vector3[] v4 = new Vector3[4];
13             v4[0] = new Vector3(ned.x, cp.y, ned.y);
14             v4[1] = new Vector3(ned.x, cp.y, fod.y);
15             v4[2] = new Vector3(fod.x, cp.y, ned.y);
16             v4[3] = new Vector3(fod.x, cp.y, fod.y);
17 
18             var minx = pos1.x < pos2.x ? pos1.x : pos2.x;
19             var maxx = minx == pos1.x ? pos2.x : pos1.x;
20             var minz = pos1.z < pos2.z ? pos1.z : pos2.z;
21             var maxz = minz == pos1.z ? pos2.z : pos1.z;
22 
23             for (int i = 0; i < v4.Length; i++)
24             {
25                 if (v4[i].x > minx && v4[i].x < maxx && v4[i].z > minz && v4[i].z < maxz)
26                 {
27                     var ncp1 = new Vector3(cp.x, cp.y, v4[i].z);
28                     var ncp2 = new Vector3(v4[i].x, cp.y, cp.z);
29 
30                     var pos1cp = ncp1.x == pos1.x || ncp1.z == pos1.z ? ncp1 : ncp2;
31                     var pos2cp = pos1cp == ncp1 ? ncp2 : ncp1;
32 
33                     LShapePos(pos1, v4[i], pos1cp);
34                     LShapePos(v4[i], pos2, pos2cp);
35                     return;
36                 }
37             }
38         }
39 
40         LineTwoPos(pos1, cp);
41         LineTwoPos(pos2, cp);
42     }

判断这四个角中哪一个点为最合适点,实在就是要判断哪个点位于这条L折线组成的矩形的局限之内,最终只会有一个点知足该情形。

 

下面是完整的毗邻剧本:

鹤岗租房网:Unity 随机舆图房间通道天生 第3张
  1 using System.Collections;
  2 using System.Collections.Generic;
  3 using UnityEngine;
  4 using System.IO;
  5 
  6 public enum ObstacleCrossType
  7 {
  8     Break,
  9     Detour
 10 }
 11 
 12 //这个剧本执行各个房间通道毗邻的具体方法
 13 public class CrossBuilder : MonoBehaviour
 14 {
 15     public GameObject CrossUnit;
 16     public ObstacleCrossType ObstacleCrossType;
 17 
 18     private MapSystem MapSystem;
 19 
 20     Vector3Int Dx = new Vector3Int(1, 0, 0);
 21     Vector3Int Dy = new Vector3Int(0, 1, 0);
 22     Vector3Int Dz = new Vector3Int(0, 0, 1);
 23 
 24     private int UnitHeight;
 25 
 26     private void Start()
 27     {
 28         MapSystem = GetComponent<MapSystem>();
 29         UnitHeight = MapSystem.RoomBuilder.FixedUnitHeight;
 30     }
 31 
 32     public IEnumerator GenCrosses()
 33     {
 34         var fr = MapSystem.MainCross.First.Value;
 35         var lr = MapSystem.MainCross.Last.Value;
 36 
 37         var frcp = new Vector3(fr.CenterPos.x, fr.PosY, fr.CenterPos.y);
 38         var lrcp = new Vector3(lr.CenterPos.x, lr.PosY, lr.CenterPos.y);
 39 
 40         Debug.Log("First: " + frcp);
 41         Debug.Log("Last: " + lrcp);
 42 
 43         foreach (var cd in MapSystem.MapData.CrossDataList)
 44         {
 45             CrossTwoRoom(cd.id1, cd.id2);
 46             yield return null;
 47         }
 48         MapSystem.bAction = false;
 49     }
 50 
 51     void CrossTwoRoom(int id1, int id2)
 52     {
 53         var from = MapSystem.MapData.RoomDataDic[id1].RoomTran;
 54         var to = MapSystem.MapData.RoomDataDic[id2].RoomTran;
 55 
 56         var frcp = new Vector3(from.CenterPos.x, from.PosY, from.CenterPos.y);
 57         var trcp = new Vector3(to.CenterPos.x, to.PosY, to.CenterPos.y);
 58 
 59         Debug.DrawLine(frcp, trcp, Color.red);
 60         Debug.Log("F:" + frcp + " " + "To: " + trcp);
 61 
 62         if (from.PosY == to.PosY)
 63         {
 64             //统一层
 65             SameYCross(from, to);
 66         }
 67         else
 68         {
 69             //差别层
 70             var rangex = CheckCommonSide(frcp.x, from.Length, trcp.x, to.Length);
 71             var rangez = CheckCommonSide(frcp.z, from.Width, trcp.z, to.Width);
 72             if (rangex.x >= rangex.y && rangez.x >= rangez.y)
 73             {
 74                 //有重叠区域
 75                 var rx = EdgeRandom(rangex.y, rangex.x);
 76                 var rz = EdgeRandom(rangez.y, rangez.x);
 77 
 78                 var fy = from.PosY - (UnitHeight - 1) * .5f + 1;
 79                 var ty = to.PosY - (UnitHeight - 1) * .5f + 1;
 80 
 81                 var miny = fy < ty ? fy : ty;
 82                 var maxy = miny == fy ? ty : fy;
 83 
 84                 for (float i = miny; i < maxy + 1; i++)
 85                 {
 86                     InsSetPos(new Vector3(rx, i, rz));
 87                 }
 88             }
 89             else
 90             {
 91                 //无重叠区域
 92                 var cp = SameYCross(from, to);
 93 
 94                 var fy = from.PosY - (UnitHeight - 1) * .5f + 1;
 95                 var ty = to.PosY - (UnitHeight - 1) * .5f + 1;
 96 
 97                 var miny = fy < ty ? fy : ty;
 98                 var maxy = miny == fy ? ty : fy;
 99 
100                 for (float i = miny; i < maxy + 1; i++)
101                 {
102                     InsSetPos(new Vector3(cp.x, i, cp.z));
103                 }
104             }
105         }
106     }
107 
108     Vector3 SameYCross(RoomTran from, RoomTran to)
109     {
110         //Test
111         if(from.CenterPos==new Vector2Int(2,21)&&to.CenterPos==new Vector2Int(19, -23))
112         {
113 
114         }
115 
116         var frcp = new Vector3(from.CenterPos.x, from.PosY, from.CenterPos.y);
117         var trcp = new Vector3(to.CenterPos.x, to.PosY, to.CenterPos.y);
118 
119         var sr = Random.value < .5f ? from : to;
120         var or = sr == from ? to : from;
121         var ry = sr.PosY - (UnitHeight - 1) * .5f + 1;
122 
123         var rangex = CheckCommonSide(frcp.x, from.Length, trcp.x, to.Length);
124         var rangez = CheckCommonSide(frcp.z, from.Width, trcp.z, to.Width);
125 
126         Vector3 pos1;
127         Vector3 pos2;
128 
129         if (rangex.y > rangex.x)
130         {
131             if (rangez.y > rangez.x)
132             {
133                 //无公共边局限
134                 var fxmax = frcp.x + (from.Length - 1) * .5f - 1;
135                 var fzmax = frcp.z + (from.Width - 1) * .5f - 1;
136 
137                 if (fxmax == rangex.x)
138                 {
139                     if (fzmax == rangez.x)
140                     {
141                         //to在from的右上
142                         var fe = Random.value < .5f ? fxmax : fzmax;
143                         if (fe == fxmax)
144                         {
145                             pos1 = new Vector3(fe + 1, ry, fzmax);
146                             pos2 = new Vector3(rangex.y, ry, rangez.y - 1);
147                             //临界值判断
148                             if (pos1.x >= pos2.x)
149                             {
150                                 pos2 = new Vector3(pos1.x + 1, ry, pos2.z);
151                             }
152 
153                             if (pos1.z >= pos2.z)
154                             {
155                                 pos1 = new Vector3(pos1.x, ry, pos2.z - 1);
156                             }
157 
158                             var cp = new Vector3(pos2.x, ry, pos1.z);
159                             LShapePos(pos1, pos2, cp);
160                         }
161                         else
162                         {
163                             pos1 = new Vector3(fxmax, ry, fe + 1);
164                             pos2 = new Vector3(rangex.y - 1, ry, rangez.y);
165 
166                             if (pos1.x >= pos2.x)
167                             {
168                                 pos1 = new Vector3(pos2.x - 1, ry, pos1.z);
169                             }
170 
171                             if (pos1.z >= pos2.z)
172                             {
173                                 pos2 = new Vector3(pos2.x, ry, pos1.z + 1);
174                             }
175 
176                             var cp = new Vector3(pos1.x, ry, pos2.z);
177                             LShapePos(pos1, pos2, cp);
178                         }
179                     }
180                     else
181                     {
182                         //to在from的右下
183                         var fe = Random.value < .5f ? fxmax : rangez.y;
184                         if (fe == fxmax)
185                         {
186                             pos1 = new Vector3(fe + 1, ry, rangez.y);
187                             pos2 = new Vector3(rangex.y, ry, rangez.x + 1);
188 
189                             if (pos1.x >= pos2.x)
190                             {
191                                 pos2 = new Vector3(pos1.x + 1, ry, pos2.z);
192                             }
193 
194                             if (pos1.z <= pos2.z)
195                             {
196                                 pos1 = new Vector3(pos1.x, ry, pos2.z + 1);
197                             }
198 
199                             var cp = new Vector3(pos2.x, ry, pos1.z);
200                             LShapePos(pos1, pos2, cp);
201                         }
202                         else
203                         {
204                             pos1 = new Vector3(rangex.x, ry, fe - 1);
205                             pos2 = new Vector3(rangex.y - 1, ry, rangez.x);
206 
207                             if (pos1.x >= pos2.x)
208                             {
209                                 pos1 = new Vector3(pos2.x - 1, ry, pos1.z);
210                             }
211 
212                             if (pos1.z <= pos2.z)
213                             {
214                                 pos2 = new Vector3(pos2.x, ry, pos1.z - 1);
215                             }
216 
217                             var cp = new Vector3(pos1.x, ry, pos2.z);                      
218                             LShapePos(pos1, pos2, cp);
219                         }
220                     }
221                 }
222                 else
223                 {
224                     if (fzmax == rangez.x)
225                     {
226                         //to在from的左上
227                         var fe = Random.value < .5f ? rangex.y : fzmax;
228                         if (fe == fzmax)
229                         {
230                             pos1 = new Vector3(rangex.y, ry, fe + 1);
231                             pos2 = new Vector3(rangex.x + 1, ry, rangez.y);
232 
233                             if (pos1.x <= pos2.x)
234                             {
235                                 pos1 = new Vector3(pos2.x + 1, ry, pos1.z);
236                             }
237 
238                             if (pos1.z >= pos2.z)
239                             {
240                                 pos2 = new Vector3(pos2.x, ry, pos1.z + 1);
241                             }
242 
243                             var cp = new Vector3(pos1.x, ry, pos2.z);
244                             LShapePos(pos1, pos2, cp);
245                         }
246                         else
247                         {
248                             pos1 = new Vector3(fe - 1, ry, rangez.x);
249                             pos2 = new Vector3(rangex.x, ry, rangez.y - 1);
250 
251                             if (pos1.x <= pos2.x)
252                             {
253                                 pos2 = new Vector3(pos1.x - 1, ry, pos2.z);
254                             }
255 
256                             if (pos1.z >= pos2.z)
257                             {
258                                 pos1 = new Vector3(pos1.x, ry, pos2.z - 1);
259                             }
260 
261                             var cp = new Vector3(pos2.x, ry, pos1.z);
262                             LShapePos(pos1, pos2, cp);
263                         }
264                     }
265                     else
266                     {
267                         //to在from的左下
268                         var fe = Random.value < .5f ? rangex.y : rangez.y;
269                         if (fe == rangex.y)
270                         {
271                             pos1 = new Vector3(fe - 1, ry, rangez.y);
272                             pos2 = new Vector3(rangex.x, ry, rangez.x + 1);
273 
274                             if (pos1.x <= pos2.x)
275                             {
276                                 pos2 = new Vector3(pos1.x - 1, ry, pos2.z);
277                             }
278                             if (pos1.z <= pos2.z)
279                             {
280                                 pos1 = new Vector3(pos1.x, ry, pos2.z + 1);
281                             }
282 
283                             var cp = new Vector3(pos2.x, ry, pos1.z);
284                             LShapePos(pos1, pos2, cp);
285                         }
286                         else
287                         {
288                             pos1 = new Vector3(rangex.y, ry, fe - 1);
289                             pos2 = new Vector3(rangex.x + 1, ry, rangez.x);
290 
291                             if (pos1.x <= pos2.x)
292                             {
293                                 pos1 = new Vector3(pos2.x + 1, ry, pos1.z);
294                             }
295                             if (pos1.z <= pos2.z)
296                             {
297                                 pos2 = new Vector3(pos2.x, ry, pos1.z - 1);
298                             }
299 
300                             var cp = new Vector3(pos1.x, ry, pos2.z);
301                             LShapePos(pos1, pos2, cp);
302                         }
303                     }
304                 }
305             }
306             else
307             {
308                 var rz = EdgeRandom(rangez.y, rangez.x);
309                 var rx1 = rangex.x + 1;
310                 var rx2 = rangex.y - 1;
311 
312                 pos1 = new Vector3(rx1, ry, rz);
313                 pos2 = new Vector3(rx2, ry, rz);
314 
315                 LineTwoPos(pos1, pos2);
316             }
317         }
318         else
319         {
320             var rx = EdgeRandom(rangex.y, rangex.x);
321             var rz1 = rangez.x + 1;
322             var rz2 = rangez.y - 1;
323 
324             pos1 = new Vector3(rx, ry, rz1);
325             pos2 = new Vector3(rx, ry, rz2);
326 
327             LineTwoPos(pos1, pos2);
328         }
329         return PosOfRoom(pos1, pos2, or);
330     }
331 
332     Vector3 PosOfRoom(Vector3 pos1, Vector3 pos2, RoomTran room)
333     {
334         var lmax = room.CenterPos.x + (room.Length - 1) * .5f;
335         var lmin = room.CenterPos.x - (room.Length - 1) * .5f;
336         var wmax = room.CenterPos.y + (room.Width - 1) * .5f;
337         var wmin = room.CenterPos.y - (room.Width - 1) * .5f;
338 
339         if (pos1.x >= lmin && pos1.x <= lmax && pos1.z >= wmin && pos1.z <= wmax)
340             return pos1;
341         else
342             return pos2;
343     }
344 
345     Vector2 CheckCommonSide(float axis1, int edge1, float axis2, int edge2)
346     {
347         var max1 = axis1 + (edge1 - 1) * .5f - 1;
348         var min1 = axis1 - (edge1 - 1) * .5f + 1;
349         var max2 = axis2 + (edge2 - 1) * .5f - 1;
350         var min2 = axis2 - (edge2 - 1) * .5f + 1;
351 
352         return new Vector2(max1 > max2 ? max2 : max1, min1 > min2 ? min1 : min2);
353     }
354 
355     float EdgeRandom(float min, float max)
356     {
357         float cut = .5f;
358         var diff = max - min;
359         if (diff % 1 == 0)
360             cut = 1f;
361         int c = (int)(diff / cut);
362 
363         return Random.Range(0, c + 1) * cut + min;
364     }
365 
366     void LineTwoPos(Vector3 pos1, Vector3 pos2)
367     {
368         if (pos1.y == pos2.y)
369         {
370             if (pos1.x == pos2.x)
371             {
372                 var min = pos1.z < pos2.z ? pos1 : pos2;
373                 var max = min.z == pos1.z ? pos2 : pos1;
374 
375                 var diff = max.z - min.z;
376 
377                 if (diff % 1 == 0)
378                 {
379                     for (float i = min.z; i <= max.z; i++)
380                     {
381                         var pos = new Vector3(min.x, min.y, i);
382 
383                         //绕路判断
384                         if (Mathf.Abs(pos.z - max.z) > 2)
385                         {
386                             if (RayCast(pos, Dz, 1))
387                             {
388                                 var posex = new Vector3(pos.x, pos.y, pos.z + 1);
389                                 var cps = MapSystem.GetExCross(posex, max);
390                                 switch (ObstacleCrossType)
391                                 {
392                                     case ObstacleCrossType.Break:
393                                         CrossBreak(pos, max, cps);
394                                         InsSetPos(posex);
395                                         break;
396                                     case ObstacleCrossType.Detour:
397                                         CrossAround(pos, max, cps);
398                                         break;
399                                 }
400                                 return;
401                             }
402                         }
403                         InsSetPos(pos);
404                     }
405                 }
406                 else
407                 {
408                     for (float i = min.z; i < max.z; i++)
409                     {
410                         var pos = new Vector3(pos1.x, pos1.y, i);
411 
412                         //绕路判断
413                         if (Mathf.Abs(pos.z - max.z) > 2)
414                         {
415                             if (RayCast(pos, Dz, 1))
416                             {
417                                 var posex = new Vector3(pos.x, pos.y, pos.z + 1);
418                                 var cps = MapSystem.GetExCross(posex, max);
419                                 switch (ObstacleCrossType)
420                                 {
421                                     case ObstacleCrossType.Break:
422                                         CrossBreak(pos, max, cps);
423                                         InsSetPos(posex);
424                                         break;
425                                     case ObstacleCrossType.Detour:
426                                         CrossAround(pos, max, cps);
427                                         break;
428                                 }
429                                 return;
430                             }
431                         }
432                         InsSetPos(pos);
433                     }
434                     InsSetPos(max);
435                 }
436             }
437             else if (pos1.z == pos2.z)
438             {
439                 var min = pos1.x < pos2.x ? pos1 : pos2;
440                 var max = min.x == pos1.x ? pos2 : pos1;
441 
442                 var diff = max.x - min.x;
443 
444                 if (diff % 1 == 0)
445                 {
446                     for (float i = min.x; i <= max.x; i++)
447                     {
448                         var pos = new Vector3(i, min.y, min.z);
449                         //绕路判断
450                         if (Mathf.Abs(pos.x - max.x) > 2)
451                         {
452                             if (RayCast(pos, Dx, 1))
453                             {
454                                 var posex = new Vector3(pos.x + 1, pos.y, pos.z);
455                                 var cps = MapSystem.GetExCross(posex, max);
456                                 switch (ObstacleCrossType)
457                                 {
458                                     case ObstacleCrossType.Break:
459                                         CrossBreak(pos, max, cps);
460                                         InsSetPos(posex);
461                                         break;
462                                     case ObstacleCrossType.Detour:
463                                         CrossAround(pos, max, cps);
464                                         break;
465                                 }
466                                 return;
467                             }
468                         }
469                         InsSetPos(pos);
470                     }
471                 }
472                 else
473                 {
474                     for (float i = min.x; i < max.x; i++)
475                     {
476                         var pos = new Vector3(i, pos1.y, pos1.z);
477                         //绕路判断
478                         if (Mathf.Abs(pos.x - max.x) > 2)
479                         {
480                             if (RayCast(pos, Dx, 1))
481                             {
482                                 var posex = new Vector3(pos.x + 1, pos.y, pos.z);
483                                 var cps = MapSystem.GetExCross(posex, max);
484                                 switch (ObstacleCrossType)
485                                 {
486                                     case ObstacleCrossType.Break:
487                                         CrossBreak(pos, max, cps);
488                                         InsSetPos(posex);
489                                         break;
490                                     case ObstacleCrossType.Detour:
491                                         CrossAround(pos, max, cps);
492                                         break;
493                                 }
494                                 return;
495                             }
496                         }
497                         InsSetPos(pos);
498                     }
499                     InsSetPos(max);
500                 }
501             }
502         }
503     }
504 
505     void LShapePos(Vector3 pos1, Vector3 pos2, Vector3 cp)
506     {
507         //判断折线中心点是否位于其他房间内,若位于,则需要重新寻路
508         var rt = MapSystem.GetRoomByPos(cp);
509         if (ObstacleCrossType == ObstacleCrossType.Detour && rt != null)
510         {
511             var to = new Vector2(rt.Length + 1, rt.Width + 1) * .5f;
512 
513             var ned = rt.CenterPos - to;
514             var fod = rt.CenterPos + to;
515 
516             Vector3[] v4 = new Vector3[4];
517             v4[0] = new Vector3(ned.x, cp.y, ned.y);
518             v4[1] = new Vector3(ned.x, cp.y, fod.y);
519             v4[2] = new Vector3(fod.x, cp.y, ned.y);
520             v4[3] = new Vector3(fod.x, cp.y, fod.y);
521 
522             var minx = pos1.x < pos2.x ? pos1.x : pos2.x;
523             var maxx = minx == pos1.x ? pos2.x : pos1.x;
524             var minz = pos1.z < pos2.z ? pos1.z : pos2.z;
525             var maxz = minz == pos1.z ? pos2.z : pos1.z;
526 
527             for (int i = 0; i < v4.Length; i++)
528             {
529                 if (v4[i].x > minx && v4[i].x < maxx && v4[i].z > minz && v4[i].z < maxz)
530                 {
531                     var ncp1 = new Vector3(cp.x, cp.y, v4[i].z);
532                     var ncp2 = new Vector3(v4[i].x, cp.y, cp.z);
533 
534                     var pos1cp = ncp1.x == pos1.x || ncp1.z == pos1.z ? ncp1 : ncp2;
535                     var pos2cp = pos1cp == ncp1 ? ncp2 : ncp1;
536 
537                     LShapePos(pos1, v4[i], pos1cp);
538                     LShapePos(v4[i], pos2, pos2cp);
539                     return;
540                 }
541             }
542         }
543 
544         LineTwoPos(pos1, cp);
545         LineTwoPos(pos2, cp);
546     }
547 
548     void CrossAround(Vector3 pos, Vector3 max, ExCross cps)
549     {
550         if (cps.pos1 != Vector3.zero && cps.pos2 != Vector3.zero && cps.pos3 != Vector3.zero)
551         {
552             LineTwoPos(pos, cps.pos1);
553             LineTwoPos(cps.pos1, cps.pos2);
554             LineTwoPos(cps.pos2, cps.pos3);
555             LineTwoPos(cps.pos3, max);
556         }
557     }
558 
559     void CrossBreak(Vector3 pos, Vector3 max, ExCross cps)
560     {
561         if (cps.pos1 != Vector3.zero && cps.pos2 != Vector3.zero && cps.pos3 != Vector3.zero)
562         {
563             InsSetPos(pos);
564             LineTwoPos(cps.pos3, max);
565         }
566     }
567 
568     bool RayCast(Vector3 ori, Vector3 dir, float mD)
569     {
570         return MapSystem.RayCast(ori, dir, mD);
571     }
572 
573     void InsSetPos(Vector3 pos, Transform parent = null)
574     {
575         var temp = MapSystem.MapData.CrossUnitPos;
576         if (!temp.Contains(pos))
577         {
578             temp.Add(pos);
579             MapSystem.CrossUnitInsts.Add(MapSystem.InsSetPos(CrossUnit, pos, parent));
580             MapSystem.MapData.CrossUnitPos = temp;
581         }
582     }
583 }
View Code

 

最终效果展示:(单层,绕过障碍)

鹤岗租房网:Unity 随机舆图房间通道天生 第5张

 

与上面统一个随机种子(断开):

 鹤岗租房网:Unity 随机舆图房间通道天生 第6张

 

关于随机种子的先容和用法可以详见之前写的另一篇博客:

https://www.cnblogs.com/koshio0219/p/12514825.html

 

下面给出打包出的unity package工具包以供参考:

https://files.cnblogs.com/files/koshio0219/RMTool.zip

,

诚信在线

诚信在线(www.hoteluniformcustom.com)现已开放诚信在线手机版下载。游戏公平、公开、公正,用实力赢取信誉。

转载声明:本站发布文章及版权归原作者所有,转载本站文章请注明文章来源:欧博亚洲(Allbet Game)!

本文链接:http://www.zbguandaobeng.com/post/1057.html

网友评论

1条评论
  • 2020-09-11 00:00:13

    欧博allbet网址欢迎进入欧博allbet网址(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。朋友们好看不

最新评论

  • 欧博代理 10/15 说:

    欧博官网手机欢迎进入欧博官网手机(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。助力助力你

  • 欧博代理 10/15 说:

    欧博官网手机欢迎进入欧博官网手机(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。助力助力你

  • UG环球网址 10/15 说:

    AllbetGmaing电脑版下载欢迎进入AllbetGmaing电脑版下载(www.aLLbetgame.us):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。无意刷到,厉害了

  • Allbet电脑版下载 10/15 说:

    欧博开户欢迎进入欧博开户(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。大家一起评论

  • AllbetAPP下载 10/14 说:

    欧博注册欢迎进入欧博注册(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。谁看的有我多

  • 环球UG客户端下载 10/13 说:

    欧博开户欢迎进入欧博开户(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。脑洞大开的感觉

  • 欧博allbet客户端 10/12 说:

    欧博allbet网址欢迎进入欧博allbet网址(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。适合大众的读物

  • 欧博代理 10/11 说:

    联博www.326681.com采用以太坊区块链高度哈希值作为统计数据,联博以太坊统计数据开源、公平、无任何作弊可能性。联博统计免费提供API接口,支持多语言接入。作者明白人