/// <summary> /// 通过性测试 /// </summary> /// <param name="args"></param> /// <param name="neighborTerrain"></param> /// <returns></returns> private static bool PassabilityTest(RolePassabilityArgs args, Terrain neighborTerrain) { return((args.CanPassMountain == false && neighborTerrain == Terrain.Mountain) || (args.CanPassWater == false && neighborTerrain == Terrain.Ocean)); }
/// <summary> /// 获取最短路径 /// </summary> /// <param name="map">游戏地图</param> /// <param name="start">起始点</param> /// <param name="end">终点</param> /// <param name="passabilityArgs">角色通过性参数</param> /// <returns>路径数组</returns> public List <Vector2Int> GetPath(GameMap map, Vector2Int start, Vector2Int end, RolePassabilityArgs passabilityArgs) { IComparer <NavigatePointArgs> NavigatePointArgsComparer = new NavigatePointArgs(); var openSet = new NavigatePointList(); var closeSet = new HashSet <Vector2Int>(); var result = new List <Vector2Int>(); var navigateCount = 0; // 寻路使用次数计数器 var navigateStartTime = DateTime.Now; // // 寻路用时计时器 openSet.Add(new NavigatePointArgs() { ActualCost = 0, ExpectCoset = 0, Position = start, Parent = null, }); while (openSet.IsEmpty()) { navigateCount++; var point = openSet.Min; openSet.Remove(point); if (point.Position != end) { closeSet.Add(point.Position); List <NavigatePointArgs> neighbors = map[point.Position.x, point.Position.y] .neighbors .Where(x => x != null && closeSet.Contains(x.Value) == false) .Select(x => { var args = this.GetNavigatePointArgs(map, point.ActualCost, x.Value, end, passabilityArgs); args.Parent = point; return(args); }).ToList(); openSet.AddRang(neighbors); } else { result = this.GetPath(point); break; } } var navigateTime = DateTime.Now - navigateStartTime; Debug.Log($"寻路完成!\n路径{string.Join("=>", result)}\n" + $"共计遍历{navigateCount}次,总耗时{navigateTime.TotalMilliseconds}ms"); return(result); }
/// <summary> /// 异步获取最短路径 /// </summary> /// <param name="map">游戏地图</param> /// <param name="start">起始点</param> /// <param name="end">终点</param> /// <param name="passabilityArgs">角色通过性参数</param> /// <returns>路径数组</returns> /// <returns></returns> public async Task <List <Vector2Int> > GetPathAsync(GameMap map, Vector2Int start, Vector2Int end, RolePassabilityArgs passabilityArgs) { return(await Task.Run(() => this.GetPath(map, start, end, passabilityArgs))); }
/// <summary> /// 获取起始点至终点的导航点参数 /// </summary> /// <param name="map">游戏地图</param> /// <param name="startCost">其实费用</param> /// <param name="start">起始点</param> /// <param name="end">终点</param> /// <param name="args">角色通过性参数</param> /// <returns></returns> private NavigatePointArgs GetNavigatePointArgs(GameMap map, int startCost, Vector2Int start, Vector2Int end, RolePassabilityArgs args) { Terrain neighborTerrain = map[start.x, start.y].Terrain; int cost = PassabilityTest(args, neighborTerrain) == true ? int.MaxValue : neighborTerrain.GetCost(); return(new NavigatePointArgs() { ActualCost = cost + startCost, ExpectCoset = this.GetExpectCoset(start, end), Position = start, }); }