逻辑代码
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. 安装Git,Maven,配置ssh认证

    安装git: yum -y install git 安装maven: wget http://mirror.bit.edu.cn/apache/maven/maven-3/3.6.1/binaries ...

  2. Git常用命令的操作

    Git命令 一.创建版本库 初始化一个Git仓库,使用git init命令. 添加文件到Git仓库,分两步: 使用命令git add <file>,注意,可反复多次使用,添加多个文件: 使 ...

  3. poj 3468 : A Simple Problem with Integers 【线段树 区间修改】

    题目链接 题目是对一个数组,支持两种操作 操作C:对下标从a到b的每个元素,值增加c: 操作Q:对求下标从a到b的元素值之和. #include<cstdio> #include<c ...

  4. 对Asycn/Await的研究

    1.async 函数就是 Generator 函数的语法糖. 例如: var fs = require('fs'); var readFile = function (fileName){ retur ...

  5. OC + RAC (九) 过滤

    // 跳跃 : 如下,skip传入2 跳过前面两个值 // 实际用处: 在实际开发中比如 后台返回的数据前面几个没用,我们想跳跃过去,便可以用skip - (void)skip { RACSubjec ...

  6. B/S文件断点上传

    一.概述 所谓断点续传,其实只是指下载,也就是要从文件已经下载的地方开始继续下载.在以前版本的HTTP协议是不支持断点的,HTTP/1.1开始就支持了.一般断点下载时才用到Range和Content- ...

  7. leetcode_1292. Maximum Side Length of a Square with Sum Less than or Equal to Threshold_[二维前缀和]

    题目链接 Given a m x n matrix mat and an integer threshold. Return the maximum side-length of a square w ...

  8. 【2019 Multi-University Training Contest 6】

    01: 02:https://www.cnblogs.com/myx12345/p/11650764.html 03: 04: 05:https://www.cnblogs.com/myx12345/ ...

  9. 循序渐进实现仿QQ界面(二):贴图按钮的三态模拟

    开始之前先说一下RingSDK的编译问题,这里演示的程序需要用到最新版本的RingSDK,请务必用SVN到svn://svnhost.cn/RingSDK更新到最新版本,推荐用TortoiseSVN. ...

  10. Linux CentOS7 安装docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口 ...