コード例 #1
0
        protected override void OnUpdate()
        {
            var mapSettings = GetSingleton <MapSettings>();
            var neighbors   = _neighbors;

            // The data is in not valid state
            if (mapSettings.Tiles.Length < 1)
            {
                return;
            }

            // Other data
            var movementComponents = GetComponentDataFromEntity <MovementCost>(true);
            var tilesSize          = mapSettings.Tiles.Length;
            var commandBuffer      = _eseCommandBufferSystem.CreateCommandBuffer();

            Entities
            .WithoutBurst()
            .WithNone <Waypoint>()
            .ForEach((Entity requestEntity, ref PathRequest pathRequest) =>
            {
                _markerAStar.Begin();

                #region Setup

                _markerSetup.Begin();
                NativeArray <float2> costs  = new NativeArray <float2>(tilesSize, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
                NativeArray <byte> closeSet = new NativeArray <byte>(tilesSize, Allocator.Temp);
                NativeArray <int> camesFrom = new NativeArray <int>(tilesSize, Allocator.Temp, NativeArrayOptions.UninitializedMemory);
                NativeMinHeap minSet        = new NativeMinHeap(tilesSize * 2, Allocator.Temp);

                _markerSetupData.Begin();
                // Setup initial data
                for (int i = 0; i < tilesSize; i++)
                {
                    costs[i] = new float2 {
                        x = 0, y = float.MaxValue
                    };
                    camesFrom[i] = -1;
                }

                _markerSetupData.End();

                // Shortcuts
                int startTile = Index1D(pathRequest.Start, tilesSize);
                int endTile   = Index1D(pathRequest.End, tilesSize);

                costs[startTile] = 0;
                _markerSetup.End();

                #endregion Setup

                #region Search

                _markerSearch.Begin();
                int lastTile = startTile;
                // While not in destination and not at dead end
                while (lastTile != endTile && lastTile != -1)
                {
                    // Mark current tile as visited
                    closeSet[lastTile] = 1;

                    for (int i = 0; i < neighbors.Length; ++i)
                    {
                        var neighbor = neighbors[i];
                        // Find linear neighbor index
                        var neighborIndex = neighbor.Of(lastTile, tilesSize);
                        // Check if neighbor exists
                        if (neighborIndex != -1)
                        {
                            // Previous + current cost
                            _markerMovementData.Begin();
                            var currentCost = movementComponents[mapSettings.Tiles[neighborIndex]];
                            _markerMovementData.End();

                            if (currentCost.Cost == MovementCost.IMPOSSIBLE)
                            {
                                closeSet[neighborIndex] = 0;
                                continue;
                            }

                            var costG = costs[lastTile].x + neighbor.Distance * currentCost.Cost;
                            var costF = costG + Implementation.Heuristic(pathRequest, neighborIndex, tilesSize);

                            if (costs[neighborIndex].y > costF)
                            {
                                // Update cost and path
                                costs[neighborIndex]     = new float2(costG, costF);
                                camesFrom[neighborIndex] = lastTile;

                                // Update min set
                                if (closeSet[neighborIndex] == 0)
                                {
                                    minSet.Push(new MinHeapNode(neighborIndex, costF));
                                }
                            }
                        }
                    }

                    lastTile = Implementation.FindCurrent(minSet, closeSet);
                }
                _markerSearch.End();

                #endregion Search

                #region ReconstructPath

                _markerReconstruct.Begin();
                var waypoints = commandBuffer.AddBuffer <Waypoint>(requestEntity);
                // Travel back through path
                while (lastTile != -1)
                {
                    waypoints.Add(new Waypoint()
                    {
                        Position = Index2D(lastTile, tilesSize)
                    });
                    lastTile = camesFrom[lastTile];
                }
                _markerReconstruct.End();

                #endregion ReconstructPath

                commandBuffer.RemoveComponent <PathRequest>(requestEntity);

                #region Cleanup

                _markerCleanup.Begin();
                // Dispose all temporary data
                costs.Dispose();
                closeSet.Dispose();
                camesFrom.Dispose();
                minSet.Dispose();
                _markerCleanup.End();

                #endregion Cleanup

                _markerAStar.End();
            }).Run();
        }
コード例 #2
0
        public void Execute()
        {
            int length  = moveCost.Length;
            int start1d = Index2dTo1d(start, moveCost_width);
            {
                for (int i = _F_.Length - 1; i != -1; i--)
                {
                    _F_[i] = float.MaxValue;
                }
                _F_[start1d] = 0;
            }
            {
                solution[start1d] = start;
            }
            {
                frontier.Push(start);
            }
            {
                visited.TryAdd(start, 0);
            }

            //solve;
            float euclideanMaxLength = EuclideanHeuristicMaxLength(length, moveCost_width);
            int2  node = int2.zero - 1;

            while (frontier.Count != 0 && math.any(node != destination))
            {
                node = frontier.Pop();                //we grab candidate with lowest F so far
                int   node1d = Index2dTo1d(node, moveCost_width);
                float node_f = _F_[node1d];

                //lets check all its neighbours:
                EnumerateNeighbours(neighbours, moveCost_width, moveCost_width, node);
                int neighboursLength = neighbours.Length;
                for (int i = 0; i < neighboursLength; i++)
                {
                    int2 neighbour   = neighbours[i];
                    int  neighbour1d = Index2dTo1d(neighbour, moveCost_width);

                    bool isOrthogonal = math.any(node == neighbour);                    //is relative position orthogonal or diagonal

                    float g = node_f + moveCost[neighbour1d] * (isOrthogonal ? 1f : 1.41421356237f);
                    float h = EuclideanHeuristicNormalized(neighbour, destination, euclideanMaxLength) * heuristic_cost;
                    float f = g + h;

                    //update F when this connection is less costly:
                    if (
                        f < _F_[neighbour1d]
                        )
                    {
                        _F_[neighbour1d]      = f;
                        solution[neighbour1d] = node;
                    }

                    //update frontier:
                    if (visited.TryAdd(neighbour, 0))
                    {
                        frontier.Push(neighbour);
                    }
                }
            }

            //create path:
            BacktrackToPath(solution, moveCost_width, destination, Results);
        }
コード例 #3
0
        private void FindPath(int2 startPosition, int2 endPosition)
        {
            Debug.Log("Pathfinding to: " + endPosition);
            if (startPosition.Equals(endPosition) || Grid[GetIndex(endPosition)] == -1)
            {
                Debug.LogError("asking to go into an obstacle, or is already there!");
                foundPath = false;

                return;
            }



            PathNode head = new PathNode(startPosition, CalculateDistanceCost(startPosition, endPosition));

            OpenSet.Push(head);



            while (itterationLimit > 0 && OpenSet.HasNext())
            {
                int      currentIndex = OpenSet.Pop();
                PathNode current      = OpenSet[currentIndex];

                int ind = GetIndex(current.Position);

                PathNode cameFromNode = CameFrom[ind];


                if (current.Position.Equals(endPosition))
                {
                    //Found our destination, we will let the cleanup job handle the path reconstruction for now
                    //ReconstructPath(startPosition, endPosition);
                    return;
                }

                float initialCost = CostSoFar[GetIndex(current.Position)];

                PathNode[] neighbourNodes = new PathNode[Neighbours.Length];

                for (int i = 0; i < Neighbours.Length; i++)
                {
                    int2 neighbour = Neighbours[i];
                    int2 position  = current.Position + neighbour;

                    if (position.x < 0 || position.x >= DimX || position.y < 0 || position.y >= DimY)
                    {
                        continue;
                    }

                    int index = GetIndex(position);

                    float cellCost = GetCellCost(currentIndex, index, true);

                    if (float.IsInfinity(cellCost))
                    {
                        current.NextToObstacle = true;



                        continue;
                    }

                    neighbourNodes[i] = new PathNode(position, cellCost);
                }

                if (!cameFromNode.Equals(null) && cameFromNode.NextToObstacle && current.NextToObstacle && IsDiagonal(current.Position, cameFromNode.Position))
                {
                    //In this case, the path came from point that was next to a obstacle, and is moving diagonally towards a point next to an obstacle. so we are assuming they are moving diagonally through the obstacle
                    //TODO: this is not always the case, will need to resolve later
                    continue;
                }

                for (int i = 0; i < neighbourNodes.Length; i++)
                {
                    int2 neighbour = Neighbours[i];

                    PathNode neighbourNode = neighbourNodes[i];

                    int index = GetIndex(neighbourNode.Position);

                    if (neighbourNode.Equals(null))
                    {
                        Debug.Log("neighbour null");
                        continue;
                    }

                    float neighbourCost = 10;

                    if ((math.abs(neighbour.x) + math.abs(neighbour.y)) == 2)
                    {
                        neighbourCost = 14;
                    }

                    float newCost = initialCost + neighbourCost + neighbourNode.ExpectedCost;
                    float oldCost = CostSoFar[index];

                    if (!(oldCost <= 0) && !(newCost < oldCost))
                    {
                        continue;
                    }

                    CostSoFar[index] = newCost;
                    CameFrom[index]  = current;


                    neighbourNode.ExpectedCost = newCost + CalculateDistanceCost(neighbourNode.Position, endPosition);


                    OpenSet.Push(neighbourNode);
                }

                itterationLimit--;
            }

            if (OpenSet.HasNext())
            {
                //We ran out of itterations

                //We will just give out where we stapped at for now
                //TODO: fix this
                var currentIndex = OpenSet.Pop();
                endPosition = OpenSet[currentIndex].Position;
            }
        }
コード例 #4
0
            public void Execute(Entity entity, int index, ref PathFindingRequest request)
            {
                _iterations    = 0;
                _pathNodeCount = 0;

                //Generate Working Containers
                var openSet   = new NativeMinHeap(MapSize, Allocator.Temp);
                var cameFrom  = new NativeArray <int>(MapSize, Allocator.Temp);
                var costCount = new NativeArray <int>(MapSize, Allocator.Temp);

                for (var i = 0; i < MapSize; i++)
                {
                    costCount[i] = int.MaxValue;
                }

                // Path finding
                var startId = request.StartId;
                var goalId  = request.GoalId;

                openSet.Push(new MinHeapNode(startId, 0));
                costCount[startId] = 0;

                var currentId = -1;

                while (_iterations < IterationLimit && openSet.HasNext())
                {
                    var currentNode = openSet[openSet.Pop()];
                    currentId = currentNode.Id;
                    if (currentId == goalId)
                    {
                        break;
                    }

                    var neighboursId = new NativeList <int>(4, Allocator.Temp);
                    Nodes[currentId].GetNeighbours(ref neighboursId);

                    foreach (var neighbourId in neighboursId)
                    {
                        //if cost == -1 means obstacle, skip
                        if (Nodes[neighbourId].GetCost() == -1)
                        {
                            continue;
                        }

                        var currentCost = costCount[currentId] == int.MaxValue
                            ? 0
                            : costCount[currentId];
                        var newCost = currentCost + Nodes[neighbourId].GetCost();
                        //not better, skip
                        if (costCount[neighbourId] <= newCost)
                        {
                            continue;
                        }

                        var priority = newCost + Nodes[neighbourId].Heuristic(goalId);
                        openSet.Push(new MinHeapNode(neighbourId, priority));
                        cameFrom[neighbourId]  = currentId;
                        costCount[neighbourId] = newCost;
                    }

                    _iterations++;
                    neighboursId.Dispose();
                }

                //Construct path
                var buffer = ResultECB.AddBuffer <PathRoute>(index, entity);
                var nodeId = goalId;

                while (_pathNodeCount < PathNodeLimit && !nodeId.Equals(startId))
                {
                    buffer.Add(new PathRoute {
                        Id = nodeId
                    });
                    nodeId = cameFrom[nodeId];
                    _pathNodeCount++;
                }

                //Construct Result
                var success = true;
                var log     = new NativeString64("Path finding success");

                if (!openSet.HasNext() && currentId != goalId)
                {
                    success = false;
                    log     = new NativeString64("Out of openset");
                }
                if (_iterations >= IterationLimit && currentId != goalId)
                {
                    success = false;
                    log     = new NativeString64("Iteration limit reached");
                }
                else if (_pathNodeCount >= PathNodeLimit && !nodeId.Equals(startId))
                {
                    success = false;
                    log     = new NativeString64("Step limit reached");
                }
                ResultECB.AddComponent(index, entity, new PathResult
                {
                    Success = success,
                    Log     = log
                });

                //Clean result at end of simulation
                CleanECB.DestroyEntity(index, entity);

                //Clear
                openSet.Dispose();
                cameFrom.Dispose();
                costCount.Dispose();
            }
コード例 #5
0
            private void FindPathUsingAStar(int startNavUnit, int endNavUnit, NativeList <int> path)
            {
                if (startNavUnit < 0 || endNavUnit < 0 ||
                    !navUnits[startNavUnit].IsNavigable() || !navUnits[endNavUnit].IsNavigable() ||
                    startNavUnit == endNavUnit)
                {
                    return;
                }

                Bounds endNavUnitBounds = navUnits[endNavUnit].GetRelativeBounds();

                // SimplePriorityQueue<int> openList = new SimplePriorityQueue<int>();
                // HashSet<int> closedList = new HashSet<int>();

                NativeMinHeap <int> openList   = new NativeMinHeap <int>(Allocator.Temp);
                NativeArray <bool>  closedList = new NativeArray <bool>(navUnits.Length, Allocator.Temp);

                int l = 0;

                for (int j = 0; j < navGridSizeY; j++)
                {
                    for (int k = 0; k < navGridSizeZ; k++)
                    {
                        for (int i = 0; i < navGridSizeX; i++)
                        {
                            navUnits[l] = navUnits[l].ResetPathFindingData();
                            l++;
                        }
                    }
                }

                openList.Push(startNavUnit, navUnits[startNavUnit].AStarData.F);

                while (openList.Size() > 0)
                {
                    int  curNavUnit = openList.Pop();
                    int3 curNavPos  = GetPosFromIndex(curNavUnit);

                    Bounds curNavUnitBounds = navUnits[curNavUnit].GetRelativeBounds();

                    for (int i = 0; i < neighborOffsets.Length; i++)
                    {
                        int3 neighborOffset = neighborOffsets[i];

                        int neighbor = GetIndexFromPos(curNavPos.x + neighborOffset.x, curNavPos.y + neighborOffset.y,
                                                       curNavPos.z + neighborOffset.z);

                        if (neighbor < 0 || !navUnits[neighbor].IsNavigable())
                        {
                            continue;
                        }

                        if (neighbor == endNavUnit)
                        {
                            navUnits[neighbor] = navUnits[neighbor].SetPathFindingParentIndex(curNavUnit);

                            BackTracePath(endNavUnit, path);
                            return;
                        }

                        if (!closedList[neighbor])
                        {
                            Bounds neighborBounds = navUnits[neighbor].GetRelativeBounds();

                            float newG = navUnits[curNavUnit].AStarData.G +
                                         Vector3.Distance(curNavUnitBounds.center, neighborBounds.center);
                            float newH = Vector3.Distance(neighborBounds.center, endNavUnitBounds.center);
                            float newF = newG + newH;

                            if (newF < navUnits[neighbor].AStarData.F)
                            {
                                navUnits[neighbor] =
                                    navUnits[neighbor].UpdatePathFindingValues(newF, newG, newH, curNavUnit);

                                openList.Push(neighbor, navUnits[neighbor].AStarData.F);
                            }
                        }
                    }

                    closedList[curNavUnit] = true;
                }

                openList.Dispose();
                closedList.Dispose();
            }