A星寻路学习记录
来源:互联网 发布:ubuntu默认账号密码 编辑:程序博客网 时间:2024/06/07 04:47
//节点
public class Node {
//节点位置public Vector3 position;//在地图中的X轴位置下标public int indexX;//在地图中的Z轴位置下标public int indexZ;//该节点是否可以行走public bool canWalk;//行走代价public float gCost;//距离目标的代价public float hCost;public float fCost { get { return gCost + hCost; } }//父节点 方便回溯路径public Node parent;public Node(Vector3 position, int indexX, int indexZ, bool canWalk){ this.position = position; this.indexX = indexX; this.indexZ = indexZ; this.canWalk = canWalk;}
}
public class Grid : MonoBehaviour {
//地图 储存所有的节点信息public Node[,] maps;//地图的长和宽public float mapSizeX;public float mapSizeZ;//每一个节点的大小 public float nodeSize;//地图长宽各占几个节点public int countX;public int countZ;//障碍物层public LayerMask canNotWalk;public static Grid instance;public List<Node> path;public void Awake(){ instance = this; Init();}//初始化 生成地图public void Init(){ //地图大小除以节点大小 算出个数 countX = Mathf.CeilToInt(mapSizeX / nodeSize); countZ = Mathf.CeilToInt(mapSizeZ / nodeSize); //初始化数组 maps = new Node[countX, countZ]; //地图赋值 for (int x = 0; x < countX; x++) { for (int z = 0; z < countZ; z++) { float posX = (this.transform.position.x - mapSizeX / 2) + nodeSize * (x + 0.5f); float posY = this.transform.position.y; float posZ = (this.transform.position.z - mapSizeZ / 2) + nodeSize * (z + 0.5f); Vector3 nodePos = new Vector3(posX, posY, posZ); bool canWalk = CheckNodeCanWalk(nodePos); Node node = new Node(nodePos, x, z, canWalk); maps[x, z] = node; } }}//检查节点是否可以行走public bool CheckNodeCanWalk(Vector3 nodePos){ return !Physics.CheckSphere(nodePos, nodeSize / 2, canNotWalk);}public void OnDrawGizmos(){ if(maps != null) { //画出地图 foreach (Node node in maps) { if( path.Contains(node)) { Gizmos.color = Color.black; Gizmos.DrawCube(node.position, Vector3.one * nodeSize * 0.8f); } else { if (node.canWalk == true) { Gizmos.color = Color.gray; Gizmos.DrawCube(node.position, Vector3.one * nodeSize * 0.8f); } else { Gizmos.color = Color.red; Gizmos.DrawCube(node.position, Vector3.one * nodeSize * 0.8f); } } } }}//通过一个位置获取一个节点信息public Node GetNodeFromVector3(Vector3 pos){ Node result = maps[0,0]; float mixDistance; mixDistance = Vector3.Distance(pos, maps[0, 0].position); for (int x = 0; x < countX; x++) { for (int z = 0; z < countZ; z++) { float distance = Vector3.Distance(pos, maps[x, z].position); if(distance < mixDistance) { mixDistance = distance; result = maps[x, z]; } } } return result;}//通过一个节点获取周围8个节点的方法public List<Node> GetNeighbourNode(Node node){ List<Node> list = new List<Node>(); for (int x = -1; x <= 1; x++) { for (int z = -1; z <= 1; z++) { if (x == 0 && z == 0) continue; int indexX = node.indexX + x; int indexZ = node.indexZ + z; if (indexX >= 0 && indexX < countX && indexZ >= 0 && indexZ < countZ) list.Add(maps[indexX, indexZ]); } } return list;}
}
public class AIPath : MonoBehaviour {
//目标点public GameObject target;//存放路径public List<Node> path = new List<Node>();// Update is called once per framevoid Update () { FindingPath(this.transform.position, target.transform.position);}//寻路void FindingPath(Vector3 startPos, Vector3 endPos){ //查找开始点和终点所处于的节点 Node startNode = Grid.instance.GetNodeFromVector3(startPos); Node endNode = Grid.instance.GetNodeFromVector3(endPos); //开关列表 开列表存放待搜索的所有节点 闭列表存放所有不需要计算的节点(例如 障碍物) List<Node> openList = new List<Node>(); List<Node> closeList = new List<Node>(); //初始点作为待搜索的第一个点 开始搜索 openList.Add(startNode); while(openList.Count > 0) { //以待搜索的第一个为起始点 Node currentNode = openList[0]; for (int i = 0; i < openList.Count; i++) { //判断代价F最小的点 或者 F相同判定H较小的点 if (openList[i].fCost < currentNode.fCost || (openList[i].fCost == currentNode.fCost && openList[i].hCost < currentNode.hCost)) { //得出最优点 currentNode = openList[i]; } } //移除这个点 openList.Remove(currentNode); //添加这个节点 不再计算 closeList.Add(currentNode); //如果得出的最优点为终点 则算出了最终路径 结束 if(currentNode == endNode) { //计算路径 GetPath(startNode, endNode); return; } //判断邻居点 哪些符合条件需要添加到待搜索列表中 foreach (Node node in Grid.instance.GetNeighbourNode(currentNode)) { //不符合条件的节点 if (node.canWalk == false || closeList.Contains(node)) { continue; } if(!openList.Contains(node)) { //符合条件的节点需要计算 node.gCost = GetDistance(node, currentNode); node.hCost = GetDistance(node, endNode); //设置父节点 方便回溯求路径 node.parent = currentNode; openList.Add(node); } } }}//计算移动代价或者到达目标点的代价 (采用几何方式计算真实距离)public float GetDistance(Node a,Node b){ return Vector3.Distance(a.position, b.position);}//计算最终路径public void GetPath(Node startNode,Node endNode){ //清除当前路径 path.Clear(); Node temp = endNode; //开始回溯 while(temp != startNode) { path.Add(temp); temp = temp.parent; } //反转 得出 由初始点到终点的路径 path.Reverse(); //传递路径 Grid.instance.path = path;}
}
阅读全文
0 0
- A星寻路学习记录
- A*算法 学习记录
- [学习记录]编译.a静态库尝试及问题记录
- A记录
- 飞凌OK6410-A学习记录1---宿主机环境配置
- A记录与MX记录
- CNAME记录和A记录
- 什么是A记录、MX记录、CNAME记录
- 什么是A记录、MX记录、CNAME记录
- A记录,CNAME记录,NS记录简介
- 什么是A记录、MX记录、CNAME记录
- 面试记录-A公司
- A记录和CNAME
- CNAME A记录区别
- --学习记录
- 学习记录
- 学习记录
- 学习记录
- unity 的游戏脚本组件的生命周期
- hibernate学习 hibernate概述
- mysql查询索引优化
- Latex编辑论文入门经验总结(1)
- Hibernate--单向多对一&&单向一对多
- A星寻路学习记录
- 自定义 MPVolumeView 外观
- Unity导出xcode项目
- lua下使用protobuf
- 转来的 cuda makefile 写法学习
- 移动购物APP设计与实现
- redis+twemproxy+socket访问
- 区块链技术应用在金融领域之大数据风控
- java和python编写二叉树