Beispiel #1
0
        public IEnumerator ComputePathAsync(IPathNode startNode, IPathNode endNode)
        {
            FindingParams findingParams = new FindingParams()
            {
                startNode    = startNode,
                endNode      = endNode,
                computedPath = new LinkedList <IPathNode>()
            };

            return(ComputePathCoroutine(findingParams));
        }
Beispiel #2
0
        public LinkedList <IPathNode> ComputePath(IPathNode startNode, IPathNode endNode)
        {
            FindingParams findingParams = new FindingParams()
            {
                startNode    = startNode,
                endNode      = endNode,
                computedPath = new LinkedList <IPathNode>()
            };
            IEnumerator coroutine = ComputePathCoroutine(findingParams);

            while (coroutine.MoveNext())
            {
                ;
            }
            return(findingParams.computedPath);
        }
Beispiel #3
0
        public IEnumerator ComputePathCoroutine(FindingParams findingParams)
        {
            //NOTE: curTicks will be different for each call.
            // if openTicks == curTicks, it means the node in in openList, same for closeList and closeTicks.
            // this is faster than reset a bool isInOpenList for all nodes before next call to this method
            int curTicks = (int)(Time.realtimeSinceStartup * 1000);

            IsComputing = true;
            if (findingParams.startNode == findingParams.endNode)
            {
                findingParams.computedPath.AddLast(findingParams.startNode);
            }
            else
            {
                //1) Add the starting square (or node) to the open list.
                m_closeList.Clear();
                m_openList.Clear();
                m_openList.AddLast(findingParams.startNode); findingParams.startNode.openTicks = curTicks;

                //2) Repeat the following:
                LinkedListNode <IPathNode> curNode;
                int iterations       = 0;
                int iterChunkCounter = k_IterationsPerProcessChunk;
                do
                {
                    ++iterations;
                    --iterChunkCounter;
                    if (iterChunkCounter == 0)
                    {
                        iterChunkCounter = k_IterationsPerProcessChunk;
                        yield return(null);
                    }

                    //a) Look for the lowest F cost square on the open list. We refer to this as the current square.
                    //curNode = m_vOpen.First(c => c.Score == m_vOpen.Min(c2 => c2.Score));
                    curNode = null;
                    for (LinkedListNode <IPathNode> pathNode = m_openList.First; pathNode != null; pathNode = pathNode.Next)
                    {
                        if (curNode == null || pathNode.Value.Score < curNode.Value.Score)
                        {
                            curNode = pathNode;
                        }
                    }

                    //b) Switch it to the closed list.
                    m_openList.Remove(curNode); curNode.Value.openTicks    = 0;
                    m_closeList.AddLast(curNode); curNode.Value.closeTicks = curTicks;

                    //c) For each of the 8 squares adjacent to this current square …
                    for (int i = 0; i < curNode.Value.GetNeighborCount(); ++i)
                    {
                        //If it is not walkable or if it is on the closed list, ignore it. Otherwise do the following.
                        IPathNode neigborNode = curNode.Value.GetNeighbor(i);
                        float     movingCost  = curNode.Value.GetNeigborMovingCost(i);
                        if (
                            neigborNode.closeTicks != curTicks && // if closeList does not contains node
                            movingCost != k_InfiniteCostValue && neigborNode.IsPassable()
                            )
                        {
                            //If it isn’t on the open list, add it to the open list. Make the current square the parent of this square. Record the F, G, and H costs of the square.
                            float newCost = curNode.Value.Cost + movingCost;
                            if (neigborNode.openTicks != curTicks) // if openList does not contains node
                            {
                                m_openList.AddLast(neigborNode); neigborNode.openTicks = curTicks;
                                neigborNode.ParentNode = curNode.Value;
                                neigborNode.Cost       = newCost;
                                neigborNode.Score      = neigborNode.Cost + neigborNode.GetHeuristic();
                                if (neigborNode == findingParams.endNode)
                                {
                                    curNode.Value = neigborNode;
                                    m_openList.Clear(); // force to exit while
                                    break;
                                }
                            }
                            //If it is on the open list already, check to see if this path to that square is better, using G cost as the measure. A lower G cost means that this is a better path.
                            else if (newCost < neigborNode.Cost)
                            {
                                //If so, change the parent of the square to the current square, and recalculate the G and F scores of the square.
                                neigborNode.ParentNode = curNode.Value;
                                neigborNode.Cost       = newCost;
                                neigborNode.Score      = neigborNode.Cost + neigborNode.GetHeuristic();
                            }
                        }
                    }
                }while (m_openList.Count > 0 && (MaxIterations <= 0 || iterations < MaxIterations));
                //Debug.Log("iterations: " + iterations);
                //d) Stop when you:
                //Add the target square to the closed list, in which case the path has been found (see note below), or
                //Fail to find the target square, and the open list is empty. In this case, there is no path.
                if (curNode.Value == findingParams.endNode)
                {
                    //3) Save the path. Working backwards from the target square, go from each square to its parent square until you reach the starting square. That is your path.
                    findingParams.computedPath.AddLast(curNode.Value);
                    do
                    {
                        curNode.Value = curNode.Value.ParentNode;
                        findingParams.computedPath.AddLast(curNode.Value);
                    }while (curNode.Value != findingParams.startNode);
                }
            }
            IsComputing = false;
            yield return(findingParams);
        }