逻辑代码
using System.Collections.Generic;
using System.Text;
using UnityEngine; namespace Game
{
public enum NodeType
{
Movable, //可移动区域
Obstacle, //障碍物
Boundary, //边界
Route //路径
} public enum NodeState
{
None, //默认
Open, //开放列表
Close //封闭列表
} public class SearchPath
{
private readonly Dictionary<Vector2, Node> m_nodes = new Dictionary<Vector2, Node>(); private readonly List<Node> list_close = new List<Node>();
private readonly List<Node> list_open = new List<Node>(); private Vector2 position_target; private Node[,] t_nodes; /// <summary>
/// 初始化地图信息
/// </summary>
/// <param name="width">宽</param>
/// <param name="height">高</param>
/// <param name="slant">斜向关联</param>
/// <returns>地图数据</returns>
public void InitMap(int width, int height, bool slant = false)
{
t_nodes = new Node[width, height]; m_nodes.Clear(); for (int i = ; i < width; i++)
{
for (int j = ; j < height; j++)
{
t_nodes[i, j] = new Node(i, j); if (i == || i == width - ||
j == || j == height - )
{
t_nodes[i, j].type = NodeType.Boundary;
} m_nodes.Add(new Vector2(i, j), t_nodes[i, j]);
}
} Vector2 key; //关联周边节点
for (int i = ; i < width; i++)
{
for (int j = ; j < height; j++)
{
if (slant)
{
for (int h = -; h <= ; h++)
{
for (int v = -; v <= ; v++)
{
if (h != || v != )
{
key = new Vector2(i + h, j + v); if (m_nodes.ContainsKey(key))
{
t_nodes[i, j].neighbour.Add(m_nodes[key]);
}
}
}
}
}
else
{
for (int k = -; k <= ; k++)
{
if (k != )
{
key = new Vector2(i + k, j); if (m_nodes.ContainsKey(key))
{
t_nodes[i, j].neighbour.Add(m_nodes[key]);
} key = new Vector2(i, j + k); if (m_nodes.ContainsKey(key))
{
t_nodes[i, j].neighbour.Add(m_nodes[key]);
}
}
}
}
}
}
} /// <summary>
/// 设置障碍物
/// </summary>
/// <param name="points">位置</param>
public void Obstacle(params Vector2[] points)
{
foreach (var key in points)
{
if (m_nodes.ContainsKey(key))
{
m_nodes[key].type = NodeType.Obstacle;
}
}
} /// <summary>
/// 寻路
/// </summary>
/// <param name="nodes">地图信息</param>
/// <param name="start">起点</param>
/// <param name="end">终点</param>
/// <returns>路径是否存在</returns>
public bool Search(Vector2 start, Vector2 end)
{
bool result = false; if (!m_nodes.ContainsKey(start) || !m_nodes.ContainsKey(end))
{
return result;
}
if (m_nodes[start].type != NodeType.Movable || m_nodes[end].type != NodeType.Movable)
{
return result;
} //设置终点
position_target = end; //重置路径
for (int i = ; i < t_nodes.GetLength(); i++)
{
for (int j = ; j < t_nodes.GetLength(); j++)
{
t_nodes[i, j].Reset();
}
} list_close.Clear();
list_open.Clear(); Node A = t_nodes[(int)start.x, (int)start.y];
A.G = ;
A.H = Vector2.Distance(position_target, A.position);
A.F = A.G + A.H;
A.parent = null;
A.state = NodeState.Close; list_close.Add(A); do
{
if (list_open.Count > )
{
A = list_open[];
}
for (int i = ; i < list_open.Count; i++)
{
if (list_open[i].F < A.F)
{
A = list_open[i];
}
} if (A.Compare(position_target))
{
result = true;
} Node B = Search(A); if (B != null)
{
do
{
B.type = NodeType.Route;
B = B.parent;
}
while (B != null);
}
list_close.Add(A);
list_open.Remove(A);
A.state = NodeState.Close;
}
while (list_open.Count > ); return result;
} private Node Search(Node A)
{
Node B; for (int i = ; i < A.neighbour.Count; i++)
{
if (A.neighbour[i] != null &&
A.neighbour[i].type == NodeType.Movable)
{
B = A.neighbour[i]; if (B.state == NodeState.None)//更新B的父节点为A,并相应更新B.G; 计算B.F,B.H; B加入OpenList
{
B.parent = A;
B.G = Vector2.Distance(A.position, B.position) + A.G;
B.H = Vector2.Distance(B.position, position_target);
B.F = B.G + B.H;
B.state = NodeState.Open; list_open.Add(B); if (B.H < Mathf.Epsilon)//B的所有父节点既是路径
{
return B;
}
}
else if (B.state == NodeState.Open)
{
float curG = Vector2.Distance(A.position, B.position); if (B.G > curG + A.G)//更新B的父节点为A,并相应更新B.G,B.H
{
B.parent = A;
B.G = curG + A.G;
B.F = B.G + B.H;
}
}
}
} return null;
} /// <summary>
/// 路径数据
/// </summary>
public List<Vector2> Output
{
get
{
List<Vector2> route = new List<Vector2>(); if (m_nodes.ContainsKey(position_target))
{
Node node = m_nodes[position_target]; while (node != null)
{
route.Add(node.position);
node = node.parent;
}
} StringBuilder sb = new StringBuilder(); for (int i = ; i < route.Count; i++)
{
sb.Append(route[i].ToString());
sb.Append("&");
} Debug.LogFormat("<color=yellow>{0}</color>", sb.ToString()); return route;
}
} public Node[,] GetNodes()
{
return t_nodes;
}
} public class Node
{
public Vector2 position; public NodeState state; public NodeType type; public float F; // F = G + H
public float G; //从起点移动到指定方格的移动代价
public float H; //从指定方格移动到终点的移动代价 public Node parent; public List<Node> neighbour = new List<Node>(); public Node(int x, int y)
{
position = new Vector2(x, y);
} public void Reset()
{
F = G = H = ; parent = null; state = NodeState.None; if (type.Equals(NodeType.Route))
{
type = NodeType.Movable;
}
} public bool Compare(Vector2 position)
{
return this.position.x == position.x &&
this.position.y == position.y;
}
}
}
调用入口 Test
using Game;
using System.Collections.Generic;
using UnityEngine; public class Test : MonoBehaviour
{
private SearchPath path_ctr; private Dictionary<Vector2, Renderer> m_map = new Dictionary<Vector2, Renderer>(); private void Awake()
{
path_ctr = new SearchPath();
} private void Start()
{
path_ctr.InitMap(, , true); for (int i = ; i < ; i++)
{
path_ctr.Obstacle(new Vector2(, i));
} for (int i = ; i < ; i++)
{
path_ctr.Obstacle(new Vector2(i, ));
} for (int i = ; i < ; i++)
{
path_ctr.Obstacle(new Vector2(i, ));
} Node[,] nodes = path_ctr.GetNodes(); InitMap(nodes); Search(new Vector2(, ), new Vector2(, ));
} private void Update()
{
if (Input.GetKeyDown(KeyCode.P))
{
Vector2 start = new Vector2(Random.Range(, ), Random.Range(, )); Vector2 end = new Vector2(Random.Range(, ), Random.Range(, )); Search(start, end);
}
} private void Search(Vector2 start, Vector2 end)
{
bool result = path_ctr.Search(start, end); if (result)
{
Debug.Log("<color=green>成功寻找到路径!</color>" + path_ctr.Output.Count);
}
else
{
Debug.LogFormat("<color=red>未寻找到路径,起始点:{0} 结束点{1}</color>", start, end);
} Node[,] nodes = path_ctr.GetNodes(); RefreshMap(nodes);
} public void InitMap(Node[,] nodes)
{
for (int i = ; i < nodes.GetLength(); i++)
{
for (int j = ; j < nodes.GetLength(); j++)
{
GameObject curCube = GameObject.CreatePrimitive(PrimitiveType.Cube);
curCube.transform.position = new Vector3(i, j, );
m_map.Add(new Vector2(i, j), curCube.GetComponent<Renderer>());
}
}
} public void RefreshMap(Node[,] nodes)
{
for (int i = ; i < nodes.GetLength(); i++)
{
for (int j = ; j < nodes.GetLength(); j++)
{
Vector2 key = new Vector2(i, j); if (m_map.ContainsKey(key))
{
if (nodes[i, j].type == NodeType.Boundary)
{
m_map[key].material.SetColor("_Color", Color.black);
}
else if (nodes[i, j].type == NodeType.Obstacle)
{
m_map[key].material.SetColor("_Color", Color.red);
}
else if (nodes[i, j].type == NodeType.Route)
{
m_map[key].material.SetColor("_Color", Color.yellow);
}
else
{
m_map[key].material.SetColor("_Color", Color.white);
}
}
}
}
}
}

参考:https://blog.csdn.net/qq_36946274/article/details/81982691

A星寻路的更多相关文章

  1. A星寻路算法介绍

    你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢? 如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! 在网上已经有很多篇关于A星寻路算法 ...

  2. 用简单直白的方式讲解A星寻路算法原理

    很多游戏特别是rts,rpg类游戏,都需要用到寻路.寻路算法有深度优先搜索(DFS),广度优先搜索(BFS),A星算法等,而A星算法是一种具备启发性策略的算法,效率是几种算法中最高的,因此也成为游戏中 ...

  3. A星寻路算法

    A星寻路算法 1.准备一个close关闭列表(存放已被检索的点),一个open开启列表(存放未被检索的点),一个当前点的对象cur 2.将cur设成开始点 3.从cur起,将cur点放入close表中 ...

  4. cocos2d-x学习日志(13) --A星寻路算法demo

    你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢?如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! A星算法简介: A*搜寻算法俗称A星 ...

  5. 无递归 A星寻路算法

    整理硬盘的时候,发现我早些年写的A星寻路算法.特放上来,待有缘人拿去,无递归噢,性能那是杠杠的. 码上伺候 public class Node { public int X { get; set; } ...

  6. A星寻路算法(A* Search Algorithm)

    你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢? 如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! 在网上已经有很多篇关于A星寻路算法 ...

  7. A星寻路算法入门(Unity实现)

    最近简单学习了一下A星寻路算法,来记录一下.还是个萌新,如果写的不好,请谅解.Unity版本:2018.3.2f1 A星寻路算法是什么 游戏开发中往往有这样的需求,让玩家控制的角色自动寻路到目标地点, ...

  8. A星寻路算法-Mind&Hand(C++)

    //注1:Mind & Hand,MIT校训,这里指的理解与实现(动脑也动手) //注2:博文分为两部分:(1)理解部分,为参考其他优秀博文的摘要梳理:(2)代码部分,是C++代码实现的,源码 ...

  9. 【Android】基于A星寻路算法的简单迷宫应用

    简介 基于[漫画算法-小灰的算法之旅]上的A星寻路算法,开发的一个Demo.目前实现后退.重新载入.路径提示.地图刷新等功能.没有做太多的性能优化,算是深化对A星寻路算法的理解. 界面预览: 初始化: ...

  10. [转载]A星寻路算法介绍

    转载自:http://www.raywenderlich.com/zh-hans/21503/a%E6%98%9F%E5%AF%BB%E8%B7%AF%E7%AE%97%E6%B3%95%E4%BB% ...

随机推荐

  1. python数据分析第二版:pandas

    一:pandas 两种数据结构:series和dataframe series:索引(索引自动生成)和标签(人为定义)组成---返回一个对象 obj = pd.Series([1,2,3,4]) ob ...

  2. voc数据集坐标,coco数据集坐标

    voc,如上图 x1 ,y1 ,x4, y4    bbox的坐标格式是,x,y的最大最小值,也就是box的左上角和右下角的坐标 coco x,y,w,h       box左上角的坐标以及宽.高 图 ...

  3. Linux g++ 编译添加 pthread

    If you are going to compile a C program with pthread.h in LINUX using GCC or G++ you will have to us ...

  4. python学习笔记(七)模块

    一个python文件就是一个模块 1.标准模块 python自带的,不需要你安装的 2.第三方模块 需要安装,别人提供的,例:pip install radis 如果提示没有pip,把python下s ...

  5. keras:InternalError: Failed to create session

    如题,keras出现以上错误,解决办法: 找到占用gpu的进程: nvidia-smi -q 杀死这些进程即可: xxxxx

  6. gradle命令行打包不同环境的apk包

    为什么我搜这个? 因为 早上在开发那边我看到他控制不同环境就是在这个下拉框选择不同的环境的 搜索词: Gradle 入门--只此一篇 https://www.jianshu.com/p/001abe1 ...

  7. DJango安装-windows

    1.进入虚拟环境后启动 activate 2.查看当前虚拟环境是否存在Django环境 pip list 3.不存在则 安装Django环境 pip install django 4.查看Django ...

  8. Linux 中设置进程通过 systemctl 启动

    对于某些脚本或需要启动命令的程序,可以通过创建 xx.service 服务文件来使用 systemctl 控制. 例如,对于 docker-compose,其后台启动且忽略输出信息的命令为: $ no ...

  9. 【ABAP系列】SAP ABAP常用函数总结第一篇

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP常用函数总结第一 ...

  10. ruby基本语法(1)

    一些学习资源 http://www.codecademy.com/zh/courses/ruby-beginner-en-d1Ylq/0/5?curriculum_id=5059f8619189a50 ...