Example #1
0
        public IEnumerator Seek()
        {
                        #if DEBUG_SEEKER
            Debug.Log("Seeker: Seek started.");
                        #endif

            m_StartTime = Time.realtimeSinceStartup;

            m_Seeking = true;

            if (m_Owner.takeShortcuts && m_Owner.DirectPath(m_StartPosition, m_EndPosition))
            // See if we can just go directly from start to end and early-out if so
            {
                                #if DEBUG_SEEKER
                Debug.Log("Seeker: DirectPath. Early out.");
                                #endif
                OnPathResult(new Path(m_StartPosition, m_EndPosition, m_Owner));
                yield break;
            }

            Waypoint startNode = Navigation.GetNearestNode(m_StartPosition, m_Owner),
                     endNode   = Navigation.GetNearestNode(m_EndPosition, m_Owner);

            if (startNode == null ||  endNode == null)
            // Unable to find either a start or an end node
            {
                                #if DEBUG_SEEKER
                Debug.Log(string.Format("Seeker: No start or end node found while trying to pathfind from {0} to {1}. Failure.", m_StartPosition, m_EndPosition));
                                #endif
                OnPathFailed();
                yield break;
            }

            if (startNode == endNode)
            // If start and end node is the same, we can early out as well
            {
                                #if DEBUG_SEEKER
                Debug.Log(string.Format("Seeker: Start and end node shared: {0}. Early out.", startNode));
                                #endif
                OnPathResult(new Path(m_StartPosition, m_EndPosition, startNode, m_Owner));
                yield break;
            }

            Dictionary <Connection, SeekerData> openSet = new Dictionary <Connection, SeekerData> ();
            foreach (Connection connection in startNode.Connections)
            {
                if (!Valid(connection))
                {
                                        #if DEBUG_SEEKER
                    Debug.Log(string.Format("Seeker: Skipping invalid connection {0}.", connection));
                                        #endif
                    continue;
                }
                openSet[connection] = new SeekerData(connection, GScore(connection), HScore(connection));
                                #if DEBUG_SEEKER
                Debug.Log("Added " + connection + " to open set.");
                                #endif
            }

            List <Connection> closedSet = new List <Connection> ();

            while (Application.isPlaying && m_Seeking)
            // Continue seeking until the end of time or we're instructed to stop
            {
                yield return(null);

                for (int i = 0; i < m_IterationCap; i++)
                // Run the maximum specified number of iterations before yielding the frame again
                {
                    if (openSet.Count == 0)
                    // No more avenues to investigate. Unable to find path.
                    {
                                                #if DEBUG_SEEKER
                        Debug.Log(string.Format("Seeker: Empty open set while trying to pathfind from {0} to {1}. Failure.", startNode, endNode));
                                                #endif
                        OnPathFailed();
                        yield break;
                    }

                    // Pick the cheapest option for investigation
                    List <SeekerData> openSetValues = new List <SeekerData> (openSet.Values);
                    openSetValues.Sort();
                    SeekerData currentPath = openSetValues[0];

                    if (currentPath.Destination == endNode)
                    // Did find the path. If still valid, return it - otherwise start over
                    {
                        Path path = new Path(m_StartPosition, m_EndPosition, currentPath, m_Owner);
                        if (path.Valid)
                        {
                            OnPathResult(path);
                            yield break;
                        }
                        else
                        {
                                                        #if DEBUG
                            Debug.Log("Seeker: Path invalidated in middle of search. Re-seeking.");
                                                        #endif
                            yield return(Seek());

                            yield break;
                        }
                    }

                    // Update the open/closed sets
                    openSet.Remove(currentPath.LastSegment);
                    closedSet.Add(currentPath.LastSegment);

                    foreach (Connection connection in currentPath.Options)
                    // Add connections leading out from this connection to the open set
                    {
                        if (!Valid(connection))
                        // Ignore invalid options
                        {
                                                        #if DEBUG_SEEKER
                            Debug.Log(string.Format("Seeker: Skipping invalid connection {0} in path {1}.", connection, currentPath));
                                                        #endif
                            continue;
                        }

                        if (closedSet.Contains(connection))
                        // Ignore already investigated options
                        {
                                                        #if DEBUG_SEEKER
                            Debug.Log(string.Format("Seeker: Skipping closed set connection {0} in path {1}.", connection, currentPath));
                                                        #endif
                            continue;
                        }

                        if (openSet.ContainsKey(connection))
                        // Ignore options we're already looking into
                        {
                                                        #if DEBUG_SEEKER
                            Debug.Log(string.Format("Seeker: Skipping open set connection {0} in path {1}.", connection, currentPath));
                                                        #endif
                            continue;
                        }

                        // Add a new option - the current path with this connection at the end
                        openSet[connection] = new SeekerData(currentPath, connection, GScore(connection), HScore(connection));

                                                #if DEBUG_SEEKER
                        Debug.Log("Added " + connection + " to open set.");
                                                #endif
                    }
                }
            }
        }