예제 #1
0
 public void Set(NPathPlanParams planParams, NPool <NPathPlanner> .NNode pathPlanner, NIPathAgent agent)
 {
     m_pathPlanParams      = planParams;
     m_pathPlanner         = pathPlanner;
     m_replanTimeRemaining = planParams.ReplanInterval;
     m_agent = agent;
 }
예제 #2
0
        public override void Awake(int maxNumberOfNodes)
        {
            base.Awake(maxNumberOfNodes);

            m_openNodes          = new NBinaryHeap <NNode>();
            m_openNodes.Capacity = maxNumberOfNodes;
            m_nodePool           = new NPool <NNode>(maxNumberOfNodes);
            m_expandedNodes      = new Dictionary <int, NPool <NNode> .NNode>(maxNumberOfNodes);
            m_solution           = new LinkedList <NNode>();
            m_reachedGoalNodeSuccessCondition = new ReachedGoalNode_SuccessCondition();
        }
예제 #3
0
        protected NPool <NNode> .NNode CreateNode(int nodeIndex)
        {
            System.Diagnostics.Debug.Assert(m_nodePool.ActiveCount == m_expandedNodes.Count);

            NPool <NNode> .NNode newNode = m_nodePool.Get();
            m_expandedNodes[nodeIndex] = newNode;
            NNode.eState nodeState = NNode.eState.kUnvisited;
            if (World.IsNodeBlocked(nodeIndex))
            {
                nodeState = NNode.eState.kBlocked;
            }
            newNode.Item.Awake(nodeIndex, nodeState);

            System.Diagnostics.Debug.Assert(m_nodePool.ActiveCount == m_expandedNodes.Count);

            return(newNode);
        }
예제 #4
0
        /// <summary>
        /// Update the current path plan by running a single cycle of the A* search. A "single A* cycle"
        /// expands a single node, and all of its neighbors. To run a full A* search, just run this function
        /// repeatedly until the function returns kSuccessfullySolvedPath, or  kFailedToSolvePath.
        /// Note that the openNodes variable is a binary heap data structure.
        ///
        /// Assumptions:		The start node has already been added to the openNodes, and the start node is the only node currently
        ///                     stored inside openNodes.
        /// </summary>
        /// <returns>
        /// Return the status of the path being solved. The path has either been solved, we failed to solve the path, or
        /// we are still in progress of solving the path.
        /// </returns>
        protected ePlanStatus RunSingleAStarCycle()
        {
            // Note: This failure condition must be tested BEFORE we remove an item from the open heap.
            if (m_openNodes.Count == 0)
            {
                return(ePlanStatus.kPlanFailed);
            }

            // The current least costing pathnode is considered the "current node", which gets removed from the open list and added to the closed list.
            NNode currentNode = m_openNodes.Remove();

            CloseNode(currentNode);

            if (PlanSucceeded(currentNode))
            {
                ConstructSolution();
                return(ePlanStatus.kPlanSucceeded);
            }
            else if (PlanFailed(currentNode))
            {
                return(ePlanStatus.kPlanFailed);
            }

            int[] neighbors    = null;
            int   numNeighbors = World.GetNeighbors(currentNode.Index, ref neighbors);

            for (int i = 0; i < numNeighbors; i++)
            {
                float actualCostFromCurrentNodeToNeighbor, testCost;
                int   neighborIndex = neighbors[i];
                if (neighborIndex == NNode.kInvalidIndex)
                {
                    // This neighbor is off the map.
                    continue;
                }

                NPool <NNode> .NNode neighbor = GetNode(neighborIndex);

                if (m_expandedNodes.Count == m_maxNumberOfNodes)
                {
                    UnityEngine.Debug.LogWarning("Pathplan failed because it reached the max node count. Try increasing " +
                                                 "the Max Number Of Nodes Per Planner variable on the PathManager, through " +
                                                 "the Inspector window.");
                    return(ePlanStatus.kPlanFailed);
                }

                switch (neighbor.Item.State)
                {
                case NNode.eState.kBlocked:
                case NNode.eState.kClosed:
                    // Case 1: Ignore
                    continue;

                case NNode.eState.kUnvisited:
                    // Case 2: Add to open list
                    RecordParentNodeAndPathCosts(neighbor.Item, currentNode);
                    OpenNode(neighbor.Item);
                    break;

                case NNode.eState.kOpen:
                    // Case 3: Update scores
                    actualCostFromCurrentNodeToNeighbor = World.GetGCost(currentNode.Index, neighbor.Item.Index);
                    testCost = currentNode.G + actualCostFromCurrentNodeToNeighbor;
                    if (testCost < neighbor.Item.G)
                    {
                        RecordParentNodeAndPathCosts(neighbor.Item, currentNode);
                        // Maintain the heap property.
                        m_openNodes.Remove(neighbor.Item);
                        m_openNodes.Add(neighbor.Item);
                    }

                    break;

                default:
                    System.Diagnostics.Debug.Assert(false, "PathNode is in an invalid state when running a single cycle of A*");
                    break;
                }
                ;
            }

            return(ePlanStatus.kPlanning);
        }