//================================================================
//
//  Copyright (C) 2017 Team Saluka
//  All Rights Reserved
//
//  Author:小妖精Balous
//
//================================================================
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Saruka
{
    /// <summary>
    /// 导航网格
    /// </summary>
    public class NavGrid : MonoBehaviour
    {
        /// <summary>
        /// 景物层级,用来建立导航网格
        /// </summary>
        public LayerMask scapeMask;
        /// <summary>
        /// 导航网格大小
        /// </summary>
        public Vector2 navGridSize;
        /// <summary>
        /// 单个网格半径
        /// </summary>
        public float gridRadius;
        /// <summary>
        /// 单个网格直径
        /// </summary>
        float gridDiameter;
        /// <summary>
        /// 网格结点
        /// </summary>
        public NavNode[,] grids
        {
            private set;
            get;
        }
        /// <summary>
        /// X轴方向网格数量
        /// </summary>
        public int gridCountX
        {
            private set;
            get;
        }
        /// <summary>
        /// Y轴方向网格数量
        /// </summary>
        public int gridCountY
        {
            private set;
            get;
        }
        /// <summary>
        /// 创建导航网格
        /// </summary>
        void CreateNavGrid()
        {
            gridDiameter = gridRadius * 2;
            gridCountX = Mathf.RoundToInt(navGridSize.x / gridDiameter);
            gridCountY = Mathf.RoundToInt(navGridSize.y / gridDiameter);
grids = new NavNode[gridCountX, gridCountY];
            //导航网格左下角,平面直角坐标系
            Vector3 navGridBottomLeft = transform.position - Vector3.right * navGridSize.x / 2 - Vector3.up * navGridSize.y / 2;
            //创建网格
            for (int x = 0; x < gridCountX; x++)
                for (int y = 0; y < gridCountY; y++)
                {
                    //网格中心坐标
                    Vector3 gridCenter = navGridBottomLeft + Vector3.right * (x * gridDiameter + gridRadius) + Vector3.up * (y * gridDiameter + gridRadius);
                    bool isWalkable = !(Physics2D.CircleCast(new Vector2(gridCenter.x, gridCenter.y), gridRadius, Vector2.zero, 0.0f, scapeMask));
                    grids[x, y] = new NavNode(gridCenter, isWalkable, x, y);
                }
        }
        /// <summary>
        /// 获得世界坐标所在的结点
        /// </summary>
        /// <param name="worldPosition">世界坐标</param>
        /// <returns>结点</returns>
        public NavNode NavNodeFromWorldPosition(Vector3 worldPosition)
        {
            worldPosition -= transform.position;
            float percentX = Mathf.Clamp01((worldPosition.x + navGridSize.x / 2) / navGridSize.x);
            float percentY = Mathf.Clamp01((worldPosition.y + navGridSize.y / 2) / navGridSize.y);
            int x = Mathf.RoundToInt((gridCountX - 1) * percentX);
            int y = Mathf.RoundToInt((gridCountY - 1) * percentY);
            return grids[x, y];
        }
        public List<NavNode> GetNeighborNodes(NavNode navNode)
        {
            List<NavNode> neighborNodes = new List<NavNode>();
            for (int x = -1; x <= 1; x++)
            {
                for (int y = -1; y <= 1; y++)
                {
                    if (x == 0 && y == 0) continue;
                    int checkX = navNode.gridX + x;
                    int checkY = navNode.gridY + y;
                    if (checkX >= 0 && checkX < gridCountX && checkY >= 0 && checkY < gridCountY) neighborNodes.Add(grids[checkX, checkY]);
                }
            }
            return neighborNodes;
        }
        void OnDrawGizmos()
        {
            //导航网格边框
            Gizmos.DrawWireCube(transform.position, new Vector3(navGridSize.x, navGridSize.y, 1));
            if(grids != null)
            {
                foreach(NavNode node in grids)
                {
                    Gizmos.color = (node.isWalkable) ? new Color(1, 1, 1, 0.4f) : new Color(1, 0, 0, 0.4f);
                    Gizmos.DrawCube(node.worldPosition, Vector3.one * (gridDiameter - 0.03f));
                }
            }
        }
        // Use this for initialization
        void Start()
        {
            CreateNavGrid();
        }
    }
}
原文:http://www.cnblogs.com/balous/p/7498692.html