예제 #1
0
        /*
         * ==== DESCRIPTION ====
         *
         * A Navigator instance is used by any object that wishes to use pathfinding.
         * The Navigator acts as a mediator between Tilemaps in a scene and pathfinding algorithms,
         * and makes extensive use of algorithms in the static MapConverter class to perform conversions.
         *
         * The Navigator is used by calling "GetWorldPath".
         * This provides a suggested path, each entry being a NodeGrid node's world coordinates.
         * Objects trying to navigate should pass in their current location and their destination,
         * then attempt to *directly* move to each node in turn (likely moving on to the next node
         * once arriving within a certain distance of the current node).
         * Calls should be made roughly every time an object's target destination changes.
         * This may be very often if chasing a moving object, so effort should be made to limit calls.
         *
         * The Navigator is handy because its inputs and outputs are world coordinates, so objects
         * have an easy time communicating with it.
         *
         * The Navigator also generates and stores all important pathfinding data (PathMaps and their contents),
         * so that each object/actor using pathfinding does not need its own copy, which saves memory.
         *
         */


        /// <summary>
        /// Get a world location to walk towards, in order to reach the desired destination.
        /// </summary>
        /// <param name="pointA">Entity's current world location.</param></param>
        /// <param name="PointB">World location of final destination.</param>
        public Vector3[] GetWorldPath(BlockingType bType, Vector3 pointA, Vector3 pointB)
        {
            PathMap      pMap      = pathMapDict[bType];
            Vector3Int   pA_vec    = MapConverter.WorldToNode(pMap, pointA);
            Vector3Int   pB_vec    = MapConverter.WorldToNode(pMap, pointB);
            Point        pA        = new Point(pA_vec.x, pA_vec.y);
            Point        pB        = new Point(pB_vec.x, pB_vec.y);
            List <Point> pointList = Pathfinder.FindPath(pMap.nodeGrid, pA, pB);

            Vector3[] coordsList = new Vector3[pointList.Count];
            int       i          = 0;

            pointList.ForEach(delegate(Point p){
                coordsList[i++] = MapConverter.NodeToWorld(pMap, p.x, p.y);
            });
            return(coordsList);
        }
예제 #2
0
 public static Vector3Int TileToNode(PathMap pathMap, int x, int y)
 {
     return(new Vector3Int(x - pathMap.bounds.xMin, y - pathMap.bounds.yMin, 0));
 }
예제 #3
0
 //based on bounds information, and matrix position, returns the TileMap location of a matrix tile
 //might not ever be used except when getting world coordinates, as in "NodeToWorld"
 public static Vector3Int NodeToTile(PathMap pathMap, int i, int j)
 {
     return(new Vector3Int(pathMap.bounds.xMin + i, pathMap.bounds.yMin + j, 0));
 }
예제 #4
0
        //converts a group of tilemaps into a matrix of booleans, for use with 2D pathfinding.
        //final matrix size is determined by tilemaps' bounds. Needs to expand to include all maps' tiles.
        //tilemaps are "flattened" into one; each boolean matrix is logically AND'd together:
        //Cells with tiles are not walkable, and convert to false. Cells without tiles convert to true.
        public static PathMap TilemapArrToPathMap(Tilemap[] maps, BoundsInt outerBounds)
        {
            if (maps == null || maps.Length == 0)
            {
                Debug.Log("Error: Navigator was given invalid references. Add maps to it in the Inspector.");
                return(new PathMap());                //TODO: make this return a completely walkable map
            }
            //outerBounds should be big enough to overlay EVERY tilemap, including the background
            BoundsInt[] bounds = new BoundsInt[maps.Length];
            for (int m = 0; m < maps.Length; m++)
            {
                bounds[m] = maps[m].cellBounds;
                if (bounds[m].xMin < outerBounds.xMin)
                {
                    outerBounds.xMin = bounds[m].xMin;
                }

                if (bounds[m].xMax > outerBounds.xMax)
                {
                    outerBounds.xMax = bounds[m].xMax;
                }

                if (bounds[m].yMin < outerBounds.yMin)
                {
                    outerBounds.yMin = bounds[m].yMin;
                }

                if (bounds[m].yMax > outerBounds.yMax)
                {
                    outerBounds.yMax = bounds[m].yMax;
                }
            }
            int i, j;             //preallocate matrix indices; x/y are for map coords, i/j for matrix indices ("nodes")

            //create bool matrix of proper size
            bool[,] boolMat = new bool[outerBounds.size.x, outerBounds.size.y];
            for (i = 0; i < outerBounds.size.x; i++)
            {
                for (j = 0; j < outerBounds.size.y; j++)
                {
                    boolMat[i, j] = true;                    //nodes are walkable (true) by default
                }
            }
            //for each map:
            for (int m = 0; m < maps.Length; m++)
            {
                //loop through positions, starting at bottom left x/y in map
                //NOTE: MAX BOUNDS ARE EXCLUSIVE
                for (int x = bounds[m].xMin; x < bounds[m].xMax; x++)
                {
                    for (int y = bounds[m].yMin; y < bounds[m].yMax; y++)
                    {
                        //convert tilemap x/y into node i/j
                        i = x - outerBounds.xMin;
                        j = y - outerBounds.yMin;
                        //set matrix bool value: null => true, else false.
                        //each map is added together: if ANY map has a tile in a location, that node is false (ie not walkable)
                        boolMat[i, j] = (boolMat[i, j] && (maps[m].GetTile(new Vector3Int(x, y, 0)) == null));
                    }    //y loop
                }        //x loop
            }            //m loop

            //return results
            PathMap pathMap = new PathMap();

            pathMap.referenceTilemap = maps[0];             //all tilemaps passed in should share a parent grid layout
            pathMap.bounds           = outerBounds;
            pathMap.nodeGrid         = new NodeGrid(outerBounds.size.x, outerBounds.size.y, boolMat);
            return(pathMap);
        }
예제 #5
0
        public static Vector3Int WorldToNode(PathMap pathMap, Vector3 pos)
        {
            Vector3Int point = pathMap.referenceTilemap.WorldToCell(pos);

            return(TileToNode(pathMap, point.x, point.y));
        }
예제 #6
0
 //finds the world coordinates of a given node. very important
 public static Vector3 NodeToWorld(PathMap pathMap, int i, int j)
 {
     return(pathMap.referenceTilemap.GetCellCenterWorld(NodeToTile(pathMap, i, j)));
 }