Пример #1
0
        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);
        }
Пример #2
0
        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);
        }