皇室战争 路线行走 (二)
改进了一下,中间的河流,做成第五区域,桥两端 分上下 两个点。
具体做法如下图
先设置10个空对象,按照固定位置排好,L代表左 R 代表右 M代表中,D下U上,都是英文首字母。 比如桥左上端,就是 LUM 左上中,因为桥是中间 。桥右下 就是 RDM 右下中。
这段代表就是把 10个节点的坐标 都保存起来,用单例,这样以后获取就不要 找来找去。
GroundVector = new Transform[10]; GameObject GroundVectors = GameObject.FindGameObjectWithTag("GroundVector"); List<Vector2> list = new List<Vector2>(); for (int i = 0; i < 10; i++) { GroundVector[i] = GroundVectors.transform.GetChild(i); list.Add(GroundVector[i].position); } GModel.getInstance.Cv.OnSetSenceVector(list); }
除了 保存 坐标,单例里面还有2个方法
1 获得区域
2 寻路
using System.Collections; using System.Collections.Generic; using UnityEngine; public class CalculationVector { public Vector2 LU;//左上 public Vector2 RU;//右上 public Vector2 LD;//左下 public Vector2 RD;//右下 public Vector2 LUM;//左上中 public Vector2 RUM;//右上中 public Vector2 LDM;//左下中 public Vector2 RDM;//右下中 public Vector2 UM;//上中 public Vector2 DM;//下中 public float Offset;//偏移量 public int region;//区域 //设置场景各个坐标 public void OnSetSenceVector(List<Vector2> list) { LU = list[0]; RU = list[1]; LD = list[2]; RD = list[3]; UM = list[4]; DM = list[5]; LUM = list[6]; RUM = list[7]; LDM = list[8]; RDM = list[9]; } //五大 区域 private int OnSetRegion(Vector2 vec) { if (LUM.x < vec.x && vec.x < DM.x)// 1,3 5区域 { if (LD.y < vec.y && vec.y < LDM.y)//1 区域 { region = 1; } else if (LDM.y < vec.y && vec.y < LUM.y) //5区域 { region = 5; } else { region = 3; } } else //2,4 5区域 { if (RD.y < vec.y && vec.y < RDM.y)//2 区域 { region = 2; } else if (RDM.y < vec.y && vec.y < RUM.y) //5区域 { region = 5; } else { region = 4; } } return region; } // 区域对应 路线 public List<Vector2> OnRoute(Vector2 v, int oneself)//判断自己还是对方 0,1 (1是自己) { int region = OnSetRegion(v); List<Vector2> list = new List<Vector2>(); switch (region) { case 1: if (oneself == 1) { if (v.y < LD.y)//如果压底部 { list.Add(LD); list.Add(LDM); list.Add(LUM); list.Add(LU); list.Add(UM); } else { list.Add(LDM); list.Add(LUM); list.Add(LU); list.Add(UM); } } else { if (v.y < LD.y)//如果压底部 { list.Add(DM); } else { list.Add(LD); list.Add(DM); } } break; case 2: if (oneself == 1) { if (v.y < RD.y)//如果压底部 { list.Add(RD); list.Add(RDM); list.Add(RUM); list.Add(RU); list.Add(UM); } else { list.Add(RDM); list.Add(RUM); list.Add(RU); list.Add(UM); } } else { if (v.y < RD.y)//如果压底部 { list.Add(DM); } else { list.Add(RD); list.Add(DM); } } break; case 3: if (oneself == 1) { if (v.y > LU.y)//如果压底部 { list.Add(UM); } else { list.Add(LU); list.Add(UM); } } else { if (v.y > LU.y)//如果压底部 { list.Add(LU); list.Add(LUM); list.Add(LDM); list.Add(LD); list.Add(DM); } else { list.Add(LUM); list.Add(LDM); list.Add(LD); list.Add(DM); } } break; case 4: if (oneself == 1) { if (v.y > RU.y)//如果压底部 { list.Add(DM); } else { list.Add(RU); list.Add(DM); } } else { if (v.y > RU.y)//如果压底部 { list.Add(RU); list.Add(RUM); list.Add(RDM); list.Add(RD); list.Add(DM); } else { list.Add(RUM); list.Add(RDM); list.Add(RD); list.Add(DM); } } break; case 5: if (oneself == 1) { if (v.x < DM.x) { list.Add(LUM); list.Add(LU); list.Add(UM); } else { list.Add(RUM); list.Add(RU); list.Add(UM); } } else { if (v.x < DM.x) { list.Add(LDM); list.Add(LD); list.Add(UM); } else { list.Add(RDM); list.Add(RD); list.Add(UM); } } break; default: break; } return list; } }
这样,用户在逻辑帧 就能随时 调用 寻路路径。速度杠杠的。
另外,如果检测 敌人,要跟踪,那么必须要 a*寻路。
为了性能,考虑2个问题。
1.格子 少一点,我觉得11 * 7 就可。1-3毫秒就能寻到,不影响性能。
2. 规定 A* 一帧使用数量,也就是说,如果当前帧有100个要用 A*寻路,那么程序假设规定最大一帧只能20个,寻路的贴上以寻,没寻的,等下一帧寻路。
好处,当然是不会卡,虽然大家会担心另外80个会不会 因为这帧不寻路 迟钝,但 逻辑帧 只要保证1秒 5帧以上,那么 这个迟钝 用户是 看不出来的,毕竟没有可能一次100个都要用a*寻路
更多优化:可以把桥 左右 做成 5,6区域。如果同区域 跟踪,可以走直线,不a*。这也是 一个优化思路。
当然,这个思路仅仅是针对 皇室战争 地图,如果同一个区域 不是 规则形状,需要绕,那么 这个只能走a*