public Dictionary <Region, Dictionary <Region, float> > InitDijkstraVertices() { var res = new Dictionary <Region, Dictionary <Region, float> >(); Cartographer cartographer = new Cartographer(); var regions = cartographer.regions; foreach (Region reg in regions) { var neighbours = cartographer.GetNeighboursUnrouted(reg.Index); var neighboursDict = new Dictionary <Region, float>(); foreach (var n in neighbours) { neighboursDict.Add(n, cartographer.GetMovementPrice(n, reg.Index)); res[reg] = neighboursDict; } } return(res); }
public PathNode GetGlobalRoute(PathNode target, PathNode position, MovementProperties movementProperties, bool onPlatform) { NavMeshHit targetArea; if (!NavMesh.SamplePosition(target.Position, out targetArea, 1f, NavMesh.AllAreas)) { return(null); } Vector3 adjustedPosition = new Vector3(position.Position.x, targetArea.position.y, position.Position.z); if (target.Distance(adjustedPosition) < movementProperties.epsilon) { return(null); } NavMeshHit currentArea; if (!NavMesh.SamplePosition(adjustedPosition, out currentArea, 1f, NavMesh.AllAreas) && !(globalPath.Count == 0) && !(globalPath.First().Type == RegionType.Moving)) { return(null); } if (NavMesh.SamplePosition(adjustedPosition, out _, 1f, NavMesh.AllAreas) && currentArea.mask == targetArea.mask) { if (targetArea.position.x - currentArea.position.x < 1f && targetArea.position.z - currentArea.position.z < 1f) { return(null); } globalPath = new List <Region>(); target.RegionId = currentArea.mask; return(target); } if (globalPath.Count == 0) { globalPath = GetPathWithDijkstra( new Region { Index = currentArea.mask, Type = RegionType.Stable }, new Region { Index = targetArea.mask, Type = RegionType.Stable }, target.Position); Cartographer cartographer = new Cartographer(); int areaMask = currentArea.mask; Vector3 inregionPosition = adjustedPosition; for (int i = 0; i < globalPath.Count(); i++) { var neighbours = cartographer.GetNeighbours(areaMask, inregionPosition); var modifiedRegion = neighbours.Find(x => x.Index == globalPath[i].Index); globalPath[i] = modifiedRegion; inregionPosition = modifiedRegion.PathPoints[0]; areaMask = modifiedRegion.Index; } } if (globalPath.Count != 0) { var nextRegion = globalPath.First(); if (currentArea.mask == nextRegion.Index) { globalPath.RemoveAt(0); if (globalPath.Count == 0) { return(target); } nextRegion = globalPath.First(); } if (nextRegion.Type == RegionType.Moving && globalPath.Count > 1 && globalPath[1].Index == currentArea.mask) { globalPath.RemoveAt(0); globalPath.RemoveAt(1); if (globalPath.Count == 0) { return(target); } nextRegion = globalPath.First(); } if (nextRegion.Type == RegionType.Stable) { return(calcStableRegionPath(nextRegion, currentArea, adjustedPosition, movementProperties)); } else if (nextRegion.Type == RegionType.Moving) { var movingRegion = (MovingRegion)nextRegion; foreach (var exit in movingRegion.ExitPoints) { //ищем точку прыжка на платформу в текущей области NavMeshHit exitHit; if (NavMesh.SamplePosition(exit.transform.position, out exitHit, 20, currentArea.mask)) { if (exitHit.mask == currentArea.mask) { if (Math.Abs(exitHit.position.x - adjustedPosition.x) < movementProperties.deltaTime * movementProperties.maxSpeed && Math.Abs(exitHit.position.y - adjustedPosition.y) < movementProperties.deltaTime * movementProperties.maxSpeed) { //Если мы в ней, то ждем платформу var node = new PathNode(movingRegion.EntryPoint.transform.position); node.RegionId = nextRegion.Index; node.JumpingPosition = true; return(node); } else { //Если не в ней, то топаем к ней var node = new PathNode(exitHit.position); node.RegionId = currentArea.mask; return(node); } } } } //Если мы уже на платформе, то идем следующий регион среди выходных точек и ждем, пока доедем //Либо если мы уже на входе в следующий регион, то топаем дальше var entryPointPosition = movingRegion.EntryPoint.transform.position; if (onPlatform) { if (globalPath.Count < 2) { //Мы уже у цели globalPath = new List <Region>(); return(null); } var exitRegion = globalPath[1]; foreach (var exit in movingRegion.ExitPoints) { NavMeshHit exitHit; if (NavMesh.SamplePosition(exit.transform.position, out exitHit, 20, exitRegion.Index)) { //Мы нашли точку выхода в следующую зону //Если мы в ней, то мы успешно прошли платформу if (Math.Abs(exitHit.position.x - adjustedPosition.x) < movementProperties.deltaTime * movementProperties.maxSpeed && Math.Abs(exitHit.position.z - adjustedPosition.z) < movementProperties.deltaTime * movementProperties.maxSpeed) { globalPath.RemoveAt(0); var node = new PathNode(exitHit.position); node.RegionId = globalPath.First().Index; return(node); } //Иначе ждем приближения точки else { var node = new PathNode(exit.transform.position); node.RegionId = nextRegion.Index; node.JumpingPosition = true; return(node); } } } } } return(new PathNode(nextRegion.PathPoints[0])); } return(null); }