void Update()
    {
        Vector3 position     = transform.position;
        Bounds  loadBounds   = new Bounds(position, LoadSize);
        Bounds  unloadBounds = new Bounds(position, LoadSize * (1f + UnloadBuffer));

        SECTR_Sector.GetContaining(ref loadSectors, loadBounds);
        SECTR_Sector.GetContaining(ref unloadSectors, unloadBounds);

        int sectorIndex = 0;
        int numSectors  = sectors.Count;

        while (sectorIndex < numSectors)
        {
            SECTR_Sector oldSector = sectors[sectorIndex];
            if (loadSectors.Contains(oldSector))
            {
                loadSectors.Remove(oldSector);
                ++sectorIndex;
            }
            else if (!unloadSectors.Contains(oldSector))
            {
                SECTR_Chunk oldChunk = oldSector.GetComponent <SECTR_Chunk>();
                if (oldChunk)
                {
                    oldChunk.RemoveReference();
                }
                sectors.RemoveAt(sectorIndex);
                --numSectors;
            }
            else
            {
                ++sectorIndex;
            }
        }

        numSectors = loadSectors.Count;
        int layerMaskValue = LayersToLoad.value;

        if (numSectors > 0)
        {
            for (sectorIndex = 0; sectorIndex < numSectors; ++sectorIndex)
            {
                SECTR_Sector newSector = loadSectors[sectorIndex];
                if (newSector.Frozen && ((layerMaskValue & (1 << newSector.gameObject.layer)) != 0))
                {
                    SECTR_Chunk newChunk = newSector.GetComponent <SECTR_Chunk>();
                    if (newChunk)
                    {
                        newChunk.AddReference();
                    }
                    sectors.Add(newSector);
                }
            }
        }

        if (locked && Loaded)
        {
            LockSelf(false);
        }

        updated = true;
    }
Beispiel #2
0
    /// Finds the shortest path through the portal graph between two points.
    /// The start and end points must currently be within Sector in the graph.
    /// <param name="path">List into which search results will be written.</param>
    /// <param name="start">The world space position at which to start the search.</param>
    /// <param name="goal">The world space goal of the search.</param>
    /// <param name="stopFlags">Flag set to test at each SECTR_Portal. A failed test will stop the traversal.</param>
    /// <returns>A list of nodes from the Start to the Goal. Empty if there is no path.</returns>
    public static void FindShortestPath(ref List <Node> path, Vector3 start, Vector3 goal, SECTR_Portal.PortalFlags stopFlags)
    {
        // This is an implementation of a basic A* search.
        // Implementation is optimized through use of a priority queue open list
        // and a dictionary for the closed list.
        path.Clear();
        openSet.Clear();
        closedSet.Clear();

        // Get the list of starting portals, all of which will be pushed on to the open set.
        // There may be multiple candidate Sectors becuase the bounding boxes may overlap.
        SECTR_Sector.GetContaining(ref initialSectors, start);
        SECTR_Sector.GetContaining(ref goalSectors, goal);

        int numInitialSectors = initialSectors.Count;

        for (int initialSectorIndex = 0; initialSectorIndex < numInitialSectors; ++initialSectorIndex)
        {
            SECTR_Sector sector = initialSectors[initialSectorIndex];
            if (goalSectors.Contains(sector))
            {
                Node newElement = new Node();
                newElement.Sector = sector;
                path.Add(newElement);
                return;
            }

            int numPortals = sector.Portals.Count;
            for (int portalIndex = 0; portalIndex < numPortals; ++portalIndex)
            {
                SECTR_Portal portal = sector.Portals[portalIndex];
                if ((portal.Flags & stopFlags) == 0)
                {
                    Node newElement = new Node();
                    newElement.Portal           = portal;
                    newElement.Sector           = sector;
                    newElement.ForwardTraversal = sector == portal.FrontSector;
                    newElement.Cost             = Vector3.Magnitude(start - portal.transform.position);
                    float estimate = Vector3.Magnitude(goal - portal.transform.position);
                    newElement.CostPlusEstimate = newElement.Cost + estimate;
                    openSet.Enqueue(newElement);
                }
            }
        }

        // Time to do some A*...
        while (openSet.Count > 0)
        {
            Node         current = openSet.Dequeue();
            SECTR_Sector sector  = current.ForwardTraversal ? current.Portal.BackSector : current.Portal.FrontSector;
            if (!sector)
            {
                continue;
            }

            // If the current element Sector contains the goal point, we're done.
            // NOTE: I *think* it's correct to end here but we should prove that
            // this is correct even strange connections of concave Sector.
            if (goalSectors.Contains(sector))
            {
                Node.ReconstructPath(path, current);
                break;
            }

            int numPortals = sector.Portals.Count;
            for (int portalIndex = 0; portalIndex < numPortals; ++portalIndex)
            {
                SECTR_Portal portal = sector.Portals[portalIndex];
                if (portal != current.Portal && (portal.Flags & stopFlags) == 0)
                {
                    // Create a new SearchElement for this neighbor.
                    Node neighborElement = new Node();
                    neighborElement.Parent           = current;
                    neighborElement.Portal           = portal;
                    neighborElement.Sector           = sector;
                    neighborElement.ForwardTraversal = sector == portal.FrontSector;
                    neighborElement.Cost             = current.Cost + Vector3.Magnitude(neighborElement.Portal.transform.position - current.Portal.transform.position);
                    float estimate = Vector3.Magnitude(goal - neighborElement.Portal.transform.position);
                    neighborElement.CostPlusEstimate = neighborElement.Cost + estimate;

                    // If the closed list already contains this portal,
                    // and that version is closer than us, we'll skip this node.
                    Node closedElement = null;
                    closedSet.TryGetValue(neighborElement.Portal, out closedElement);
                    if (closedElement != null && closedElement.CostPlusEstimate < neighborElement.CostPlusEstimate)
                    {
                        continue;
                    }

                    // Check to see if the neighbor is already on the open list.
                    Node openElement = null;
                    for (int i = 0; i < openSet.Count; ++i)
                    {
                        if (openSet[i].Portal == neighborElement.Portal)
                        {
                            openElement = openSet[i];
                            break;
                        }
                    }
                    // Skip this neighbor if the open neighbor is better than us.
                    if (openElement != null && openElement.CostPlusEstimate < neighborElement.CostPlusEstimate)
                    {
                        continue;
                    }

                    // Add this neighbor to the open list.
                    openSet.Enqueue(neighborElement);
                }
            }

            // Once all neighbors are considered, put this node onto the close list.
            if (!closedSet.ContainsKey(current.Portal))
            {
                closedSet.Add(current.Portal, current);
            }
        }
    }