コード例 #1
0
        public static List <NavMeshCell> CalculateNavMeshCells(Grid grid)
        {
            NavMeshCell.ResetMeshIDs();
            Grid = grid;

            for (int col = 0; col < Grid.Cols; col++)
            {
                for (int row = 0; row < Grid.Rows; row++)
                {
                    Grid[col, row].MeshID = Cell.NOT_PART_OF_MESH;
                }
            }

            startAt = new Point(Grid.Cols / 2, Grid.Rows / 2);
            Grid[startAt].Passable = true;
            //startAt = new Point(0, 0);
            finishedCalculating = false;
            blockedEast         = false;
            blockedSouth        = false;
            blockedWest         = false;
            blockedNorth        = false;

            navCells = new List <NavMeshCell>();
            curCell  = new NavMeshCell(Grid[startAt].Pos, Grid.CellSize, Grid.CellSize);
            frontier = new List <Cell>();

            while (!finishedCalculating)
            {
                // If cell is becoming long and skinny, restrict expansion on that axis.

                // Restrict East / West expansion
                if (curCell.Width >= curCell.Height * 3)
                {
                    blockedEast = true;
                    blockedWest = true;
                }

                // Restrict North / South expansion
                if (curCell.Height >= curCell.Width * 3)
                {
                    blockedNorth = true;
                    blockedSouth = true;
                }

                // Try to expand east.
                if (!blockedEast)
                {
                    blockedEast = DoNewCellsBlock(GetNextEastCol(curCell));

                    // Expansion is valid.
                    if (!blockedEast)
                    {
                        // Increase size of current cell.
                        curCell.Width += Grid.CellSize;
                    }
                }

                // Try to expand south.
                if (!blockedSouth)
                {
                    blockedSouth = DoNewCellsBlock(GetNextSouthRow(curCell));

                    // Expansion is valid
                    if (!blockedSouth)
                    {
                        // Increase size of current cell.
                        curCell.Height += Grid.CellSize;
                    }
                }

                // Try to expand west.
                if (!blockedWest)
                {
                    blockedWest = DoNewCellsBlock(GetNextWestCol(curCell));

                    // Expansion is valid
                    if (!blockedWest)
                    {
                        // Increase size of current cell.
                        curCell.Width += Grid.CellSize;
                        curCell.Pos.X -= Grid.CellSize;
                    }
                }

                // Try to expand north.
                if (!blockedNorth)
                {
                    blockedNorth = DoNewCellsBlock(GetNextNorthRow(curCell));

                    // Expansion is valid.
                    if (!blockedNorth)
                    {
                        // Increase size of current cell.
                        curCell.Height += Grid.CellSize;
                        curCell.Pos.Y  -= Grid.CellSize;
                    }
                }

                // Blocked on both dimensinos, finalise this nav mesh cell.
                if (BlockedOnAllSides)
                {
                    // Finish making this cell and start making a new one.
                    // Probably calculate neighbours here too.
                    uint nextMeshID = NavMeshCell.NextMeshID;
                    curCell.NavMeshID = nextMeshID;
                    AddNavCell(curCell);

                    // Assign each cell in the area as part of the new Nav Mesh Cell.
                    foreach (Cell c in Grid.CellsInRect(curCell.CollisionRect.GetInflated(-1, -1)))
                    {
                        c.MeshID = nextMeshID;
                    }

                    // Update frontier to remove any cells now part of the mesh
                    for (int i = frontier.Count - 1; i >= 0; i--)
                    {
                        if (frontier[i].MeshID != Cell.NOT_PART_OF_MESH)
                        {
                            frontier.RemoveAt(i);
                        }
                    }

                    // Get surrounding cells.
                    var newCells = GetNextBorder(curCell);

                    foreach (Cell c in newCells)
                    {
                        // Add to frontier if valid
                        if (c.Passable && c.MeshID == Cell.NOT_PART_OF_MESH)
                        {
                            frontier.Add(c);
                        }
                    }

                    if (frontier.Count == 0)
                    {
                        finishedCalculating = true;
                    }

                    if (!finishedCalculating)
                    {
                        startAt      = Grid.IndexAt(frontier[0].Mid);
                        curCell      = new NavMeshCell(Grid[startAt].Pos, Grid.CellSize, Grid.CellSize);
                        blockedEast  = false;
                        blockedSouth = false;
                        blockedNorth = false;
                        blockedWest  = false;
                    }
                }
            }

            CalculateNeighbours();
            return(navCells);
        }