Unity的A-Star算法在游戏中的实现
用Unity引擎制作AR小游戏

用Unity引擎制作AR小游戏Unity引擎是一款强大的开发工具,具备制作虚拟现实和增强现实游戏的能力。
本文将探讨如何利用Unity引擎制作AR小游戏。
首先,开发AR小游戏前需要明确游戏的目标和设计。
在设计阶段,可以考虑以下几个方面:1. 游戏类型:选择最适合AR技术的游戏类型。
例如,互动解谜游戏、射击游戏或跑酷游戏等。
2. 游戏场景:选择一个与游戏类型相匹配的场景,在Unity中进行建模和设计。
场景中需要考虑光照、纹理和音效等因素,以增强游戏的真实感。
3. 游戏角色和物体:设计游戏中的角色和物体,使其能够与现实世界进行交互。
借助Unity的物理引擎,可以模拟真实世界中的运动和碰撞。
4. 游戏机制:确定游戏的规则和机制,以及用户与虚拟内容之间的互动方式。
这可以包括手势识别、触控热点或声音控制等功能。
一旦设计完成,就可以开始使用Unity引擎开发AR小游戏了。
下面是一个基本的开发流程:1. 导入AR插件:Unity支持各种AR插件,如Vuforia、ARKit和ARCore等。
选择合适的插件,并按照说明进行导入和设置。
2. 导入场景和资源:将之前设计好的场景和所需的资源(包括模型、材质和音效等)导入到Unity中。
3. 设置相机:根据AR插件的要求,设置相机的参数以适应增强现实环境。
这可以包括调整透视、投影和追踪的设置。
4. 编写游戏逻辑:使用Unity的脚本语言(如C#)编写游戏的逻辑代码。
这包括角色移动、碰撞检测和触发事件等功能。
5. 部署和测试:编译游戏,并在支持AR的设备上进行测试。
确保游戏在现实世界中能够正确显示和交互。
制作AR小游戏需要一定的开发经验和技巧。
以下是一些值得注意的事项:1. 性能优化:AR游戏通常需要消耗大量的计算资源。
在开发过程中,要注意对模型和纹理等资源进行优化,以提高游戏的性能和稳定性。
2. 用户体验:AR游戏要尽可能提供流畅的用户体验。
确保虚拟内容与现实世界的衔接自然,并提供清晰的指导和反馈。
A-star-算法-八数码问题-C++-报告+代码+详细注释1

二、程序运行测试A*算法求解八数码问题一、详细设计说明1.评价函数以当前状态下各将牌到目标位置的距离之和作为节点的评价标准。
距离的定义为: “某将牌行下标与目标位置行下标之差的绝对值 + 列下标与目标位置列下标之差的绝对值”。
距离越小, 该节点的效果越好。
某个状态所有将牌到目标位置的距离之和用“h值”表示。
2.主要函数2.1countH(state & st);countH函数功能是计算st状态的h值。
2.2计算过程中将会用到rightPos数组, 数组里记录的是目标状态下, 0~9每个将牌在九宫格里的位置(位置 = 行下标 * 3 + 列下标)。
2.3f(state * p);f()=h()+level2.4look_up_dup(vector<state*> & vec, state * p);2.5在open表或close表中, 是否存在指定状态p, 当找到与p完全相等的节点时, 退出函数。
2.6search(state & start);在open表不为空时, 按f值由小到大对open表中元素进行排序。
调用findZero()函数找到0值元素的位置。
空格可以向上下左右四个方向移动, 前提是移动后不能越过九宫格的边界线。
确定某方向可走后, 空格移动一步, 生成状态p’。
2.7此时, 检查open表中是否已有p’, 若有, 更新p’数据;检查close表中是否已有p’, 若有, 将p’从close表中删除, 添加到open表中。
2.8重复的执行这个过程, 直到某状态的h值为零。
2.9dump_solution(state * q);在终端输出解路径。
// A*算法八数码问题#include"stdafx.h"#include<iostream>#include<vector>#include<time.h>#include<algorithm>using namespace std;const int GRID = 3; //Grid表示表格的行数(列数), 这是3*3的九宫格int rightPos[9] = { 4, 0, 1, 2, 5, 8, 7, 6, 3 };//目标状态时, 若p[i][j]=OMG,那么3*i+j = rightPos[OMG]struct state{int panel[GRID][GRID];int level; //记录深度int h;state * parent;state(int level) :level(level){}bool operator == (state & q){//判断两个状态是否完全相等(对应位置元素相等), 完全相等返回true,否则返回falsefor (int i = 0; i<GRID; i++){for (int j = 0; j<GRID; j++){if (panel[i][j] != q.panel[i][j])return false;}}return true;}state & operator = (state & p){ //以状态p为当前状态赋值, 对应位置元素相同for (int i = 0; i<GRID; i++){for (int j = 0; j<GRID; j++){panel[i][j] = p.panel[i][j];}}return *this;}};void dump_panel(state * p){ //将八数码按3*3矩阵形式输出for (int i = 0; i<GRID; i++){for (int j = 0; j<GRID; j++)cout << p->panel[i][j] << " ";cout << endl;}}int countH(state & st){ //给定状态st, 计算它的h值。
E n i g m a 算 法 详 解

成为专业程序员路上用到的各种优秀资料、神器及框架本文是鄙人工作这几年随手收集整理的一些自认为还不错的资料,成长的道理上需要积累,这么长时间了,是时候放出来分享下了,或许能帮助到你。
欢迎点赞,让更多人看到,让福利普照。
因为本文以后不会更新,但项目依旧会更新。
所以,更好的做法是,请到GitHub上Star:stanzhai-be-a-professional-programmer成为一名专业程序员的道路上,需要坚持练习、学习与积累,技术方面既要有一定的广度,更要有自己的深度。
笔者作为一位tool mad,将工作以来用到的各种优秀资料、神器及框架整理在此,毕竟好记性不如烂键盘,此项目可以作为自己的不时之需。
本人喜欢折腾,记录的东西也比较杂,各方面都会有一些,内容按重要等级排序,大家各取所需。
这里的东西会持续积累下去,欢迎Star,也欢迎发PR给我。
技术站点必看书籍大牛博客GitHub篇工具篇平台工具常用工具第三方服务爬虫相关(好玩的工具)安全相关Web服务器性能-压力测试工具-负载均衡器大数据处理-数据分析-分布式工具Web前端语言篇C游戏开发相关日志聚合,分布式日志收集RTP,实时传输协议与音视频技术站点在线学习:Coursera、edX、Udacity?-way to explore国内老牌技术社区:OSChina、博客园、CSDN、51CTO 免费的it电子书:ITeBooks - Free Download - Big Library在线学习:UdemyCrowd-sourced code mentorship. and Practicecoding with fun programming challenges - CodinGameDevStore:开发者服务商店MSDN:微软相关的官方技术集中地,主要是文档类必看书籍SICP(Structureand Interpretation of Computer Programs)深入理解计算机系统代码大全2人件人月神话软件随想录算法导论(麻省理工学院出版社)离散数学及其应用设计模式编程之美黑客与画家编程珠玑The Little SchemerSimply Scheme_Introducing_Computer_ScienceC++ PrimeEffective C++TCP-IP详解Unix 编程艺术技术的本质软件随想录计算机程序设计艺术职业篇:程序员的自我修养,程序员修炼之道,高效能程序员的修炼《精神分析引论》弗洛伊德《失控》《科技想要什么》《技术元素》凯文凯利程序开发心理学天地一沙鸥搞定:无压力工作的艺术大牛博客云风(游戏界大牛): 云风的Tian (binghe)R大【干货满满】RednaxelaFX写的文章-回答的导航帖陈皓-左耳朵耗子:酷壳 - CoolShellJeff Atwood(国外知名博主): CodingHorror阮一峰(黑客与画家译者,Web):RuanYiFeng’s Personal Website廖雪峰(他的Python、Git教-程不少人都看过):HomeGitHub篇Awesome:这是个Awesome合集,常见的资料这里面都能找到Awesome2:类似第一个Awesome杂七杂八、有用没用的Awesome合集非常不错的语言类学习资料集合:Awesomenessawesome-ios-uiawesome-android-uiAwesome-MaterialDesi gnawesome-public-datasetsawesome-AppSec(系统安全)awesome-datascience书籍资料free-programming-books中文版免费的编程中文书籍索引《程序员编程艺术—面试和算法心得》GoBooksPapersLearning)深入学习(Deep Learning)资料Docker资料合集学习使用StromHadoopInternalsSparkInternals大数据时代的数据分析与数据挖掘in DatabasesDataScience blogs日志:每个软件工程师都应该知道的有关实时数据的统一概念AndroidCode PathAndroidLearn NotesPHP类库框架,资料集合优秀项目Design开源项目Android开源项目分类汇总前端 Node.jsGuide的中文分支Angular2学习资料AngularJS应用的最佳实践和风格指南React-Native学习指南七天学会NodeJSnode.js中文资料导航Nodejs学习路线图如何学习nodejs工作,工具系统管理员工具集合ProGitNginx开发从入门到精通Google全球 IP 地址库收集整理远程工作相关的资料Colorschemes for hackers游戏开发工具集,MagicTools开发者工具箱, free-for-devGitHub秘籍Git风格指南Bast-App平台工具常用工具Mac下的神兵利器asciinema:- 免费在线作图,实时协作Origami: 次世代交互设计神器百度脑图:百度脑图第三方服务DnsPod:一个不错的只能DNS服务解析提供商DigitalOcean:海外的云主机提供商,价格便宜,磁盘是SSD的,用过一段时间整体上还可以,不过毕竟是海外的,网速比较慢。
A_star算法

Amit's A star Page中译文译序这篇文章很适合A*算法的初学者,可惜网上没找到翻译版的。
本着好东西不敢独享的想法,也为了锻炼一下英文,本人译了这篇文章。
由于本人英文水平非常有限,六级考了两次加一块不超过370分,因此本译文难免存在问题。
不过也算是抛砖引玉,希望看到有更多的游戏开发方面的优秀译作出现,毕竟中文的优秀资料太少了,中国的游戏开发者的路不好走。
本人能力有限,译文中有小部分词句实在难以翻译,因此暂时保留英文原文放在译文中。
对于不敢确定翻译是否准确的词句,本人用圆括号保留了英文原文,读者可以对照着加以理解。
A*算法本身是很简单的,因此原文中并没有过多地讨论A*算法本身,而是花了较大的篇幅讨论了用于保存OPEN和CLOSED集的数据结构,以及A*算法的变种和扩展。
编程实现A*是简单的,读者可以用STL对本文中的伪代码加以实现(本人已花一天时间实验过基本的A*搜索)。
但是最重要的还是对A*本身的理解,这样才可以在自己的游戏中处理各种千变万化的情况。
翻译本文的想法产生于2006年5月,实际完成于2007年4月到6月,非常惭愧。
最后,本译文仅供交流和参考,对于因本译文放到网上而产生的任何问题,本人不负任何责任。
蔡鸿于南开大学软件学院2007年6月9日原文地址:/~amitp/GameProgramming/相关链接:/%7Eamitp/gameprog.html#Paths我们尝试解决的问题是把一个游戏对象(game object)从出发点移动到目的地。
路径搜索(Pathfinding)的目标是找到一条好的路径——避免障碍物、敌人,并把代价(燃料,时间,距离,装备,金钱等)最小化。
运动(Movement)的目标是找到一条路径并且沿着它行进。
把关注的焦点仅集中于其中的一种方法是可能的。
一种极端情况是,当游戏对象开始移动时,一个老练的路径搜索器(pathfinder)外加一个琐细的运动算法(movement algorithm)可以找到一条路径,游戏对象将会沿着该路径移动而忽略其它的一切。
Unity的A-Star算法在游戏中的实现

Unity的A-Star算法在游戏中的实现Unity 的A-Star 算法在游戏中的具体实现寻路算法在游戏开发中有着广泛的应用,广泛应用的寻路算法有三种:迪杰斯特拉算法、A-Star算法、BFS。
迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法。
是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题。
迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止广泛应用于单源最短路径问题上。
A-Star 搜寻算法俗称A星算法。
A-Star 算法是比较流行的启发式搜索算法之一,被广泛应用于路径优化领域。
它的独特之处是检查最短路径中每个可能的节点时引入了全局信息,对当前节点距终点的距离做出估计,并作为评价该节点处于最短路线上的可能性的量度。
BFS(Bi-Directional Breadth-First-Search)双向广度优先搜索算法,数据结构的书中对此有详细的介绍。
在这三种算法中A-Star 算法在游戏开发中使用最为广泛。
这里主要介绍的就是A-Star 算法在游戏开发中的实际应用。
AStar 算法思想A* 搜索算法结合了基于广度搜索的迪杰斯特拉算法的BFS 最佳优先搜索优点的最短路径算法。
其思想是将节点的邻近节点加入带处理的队列中,通过某个评估函数,依据函数有优先级的对处理队列中的节点进行评估。
公式表示为:F(n)=G(n)+H(n)。
其中F(n) 是从初始状态经由状态n 到目标状态的代价估计,G(n) 是某个状态空间中从开始的状态到状态n 实际所要付出的代价,(n) 从状态n 到目标状态的最优路径估计的代价。
实际使用当中在地图当中找到所需的目标节点。
首先要将节点分为四类:可通过节点、不可通过节点、开始节点、目标节点。
两种队列:开启队列(open-list)、关闭队列(close-list)。
开启队列的内容:开启队列里面是一些可能构成最短路径的节点。
Unity中调用Awake,Start,Update等方法的原理机制

Unity中调⽤Awake,Start,Update等⽅法的原理机制⾸先声明这⾥的理解并不是官⽅释义,只是舶主根据晚上的各位⼤佬的关点理解总结的,如果有什么不对的地⽅希望⼤家指正:作为Unity中的⽣命周期准确的闹明⽩它的实现原理还是很重要的我认为。
⽣命周期⽅法的实现机制实际上是⼀种类反射机制。
Uniy引擎整体是架设在mono IDE基础上的。
mono IDE是⽀持通过string来查找⽅法的,且和真正的反射⼀样是能够查找调⽤私有⽅法的,当找到这些⽅法后会存下指针,待使⽤。
在引擎内部存在⼀张表,这张表的形成是通过在场景中查找全部的MonoBehaviour类型脚本然后便利⾥⾯的⽅法,将需要的调⽤的⽅法是全部记录下来,然后进⾏调⽤。
防⽌那些不需要调⽤的MonoBehaviour中的⽅法占⽤空间,节省资源开耗。
Mono的API可能效率更⾼,但对于单次调⽤,性能仍然逊于虚⽅法调⽤。
反射实际上是开销⾮常⼤的调⽤⽅式,⽐之虚⽅法来说要⾼得多,因此Unity选择使⽤反射并⾮是出于性能⽅⾯的考虑。
实际上,每帧调⽤的这些事件⽅法从数量级上来说是很卑微的,反射造成的性能影响亦可忽略不计。
Unity使⽤这种事件机制的根本原因是出于对灵活性的考虑。
Unity采⽤组件式设计,触发⼀个事件,需要通知到相应gameobject的所有组件。
如果使⽤多态来实现,则必须假设所有组件都派⽣⾃包含此事件的基类,或者筛选出派⽣⾃此基类的组件逐⼀通知。
这样⼀来是⿇烦,⼆来则容易带来复杂的继承关系,与组件式这种倡导⽤聚合代替继承的设计从理念上就是相悖的。
另⼀⽅⾯的原因则是为了跟JS保持⼀致性。
这种事件机制对于JS这种动态类型语⾔来说是浑然天成的。
这种设计最⼤的缺陷在于事件名通过字符串耦合,如此⼀来,完全绕开了编译期静态检查,⽆法为事件调⽤的正确性提供保障;在复杂的系统⾥,也可能因为事件重名⽽导致bug。
Unity的确是通过反射来调⽤脚本的⽅法的,并且这⼀过程会在运⾏时不停对所有MonoBehaviour遍历进⾏。
A星算法详解

pnode->father = pnode_now;
if (orient % 2 == 0)
{
pnode->g = pnode->father->g + 10;
} else {
pnode->g = pnode->father->g + 14; } pnode->f = pnode->g + pnode->h; Openlist2.push_front(pnode); } Openlist2.sort(cmp<Node*>()); mygraph.Loc[pnode->loc_y][pnode->loc_x] = INOPEN; vect_node.push_back(pnode); //system("choice /t 0.5 /d y /n >nul"); system("pause"); system("cls"); mygraph.map(); }
6. 如果某个相邻方格 D 已经在 "开启 列表" 里了, 检查如果用新的路径 (就是经过 C 的路径) 到达它的话, G值是否会更低一些, 如果新的G值更低, 那就把它的 "父方格" 改 为目前选中的方格 C, 然后重新计算它的 F 值和 G 值 (H 值不需要重新计算, 因为对于 每 较个 高方 , 就C块o说p, yH明ri经g值h过是t ©不C2变0再1的到6 )C达. r如eDa果t不e新C是的h一enG个值明比智 的选择, 因为它需要更远的路, 这时我们什么 也不做.
简易的A星算法自动寻路(C#)

简易的A星算法⾃动寻路(C#)路径计算⽅式(详见参考:堪称最好最全的A*算法详解(译⽂)):1. 曼哈顿距离,横向和纵向直线距离,仅限于横向纵向移动2. 对⾓线距离,对⾓线 + 直线,可以横向、纵向、对⾓线⽅向移动3. 欧⼏⾥得距离,任意⾓度直线,任意⽅向移动using System.Collections;using System.Collections.Generic;using UnityEngine;using System.Linq;public class AStartTest{AStarNode[,] nodeMap = new AStarNode[10, 10];void CheckAndFindPath(AStarNode startNode, AStarNode endNode){//计算路径List<AStarNode> pathNodes = FindNodePath(startNode, endNode, nodeMap);if (pathNodes == null || pathNodes.Count == 0)return;//计算路径折点List<AStarNode> pathPoints = GetPathPoint(pathNodes);}//计算路径折点List<AStarNode> GetPathPoint(List<AStarNode> path){List<AStarNode> tmpPointList = new List<AStarNode>();//⽆折点if (path.Count <= 2)return tmpPointList;//当前节点与前⼀节点的位置关系(X坐标相同或Y坐标相同)bool lastDirIsX = path[1].pos.x == path[0].pos.x;//计算折点for (int i = 2; i < path.Count; i++){//若与前⼀节点X坐标相同if (path[i].pos.x == path[i - 1].pos.x){//前两个节点时Y坐标相同,即为折点if (!lastDirIsX){//记录折点,记录当前节点关系tmpPointList.Add(path[i - 1]);lastDirIsX = true;}}else{if (lastDirIsX){tmpPointList.Add(path[i - 1]);lastDirIsX = false;}}}//路径最后节点也视为折点tmpPointList.Add(path[path.Count - 1]);//return tmpPointList;}#region --- A*算法 ---//计算最短有效路径List<AStarNode> openList = new List<AStarNode>();List<AStarNode> closeList = new List<AStarNode>();List<AStarNode> aroundNodes;List<AStarNode> FindNodePath(AStarNode startNode, AStarNode endNode, AStarNode[,] allNodes) {//计算范围内的节点openList.Clear();//不在计算范围内的节点closeList.Clear();//添加起点openList.Add(startNode);AStarNode curNode;//从起点开始循环判断while (openList.Count > 0){//初始当前位置curNode = openList[0];//计算最优当前位置for (int i = 0; i < openList.Count; i++){//F:从起点到⽬标点的移动步数//H:从当前位置到⽬标位置的移动步数if (openList[i].CostF < curNode.CostF && openList[i].costH < curNode.costH){curNode = openList[i];}}//锁定当前位置节点openList.Remove(curNode);closeList.Add(curNode);////已经计算到⽬标点//if (curNode.Equals(endNode))//{// //返回最优路径// return GetPathWithNode(startNode, endNode);// }//未计算到⽬标点, 继续//获取当前点的周围节点, 在周围节点中查找下⼀步的最优节点aroundNodes = GetAroundNodes(curNode, allNodes);for (int i = 0; i < aroundNodes.Count; i++){//计算到⽬标点if (aroundNodes[i].Equals(endNode)){//设置上⼀节点aroundNodes[i].lastNode = curNode;//返回最优路径return GetPathWithNode(startNode, endNode);}//不是⽬标点, 继续计算, 剔除周围节点不可通过、在不可计算范围内的节点if (!aroundNodes[i].isWall && !closeList.Contains(aroundNodes[i])){//计算 G H F//F:从起点到⽬标点的移动步数//G:从起点到当前位置的移动步数int newCostG = curNode.costG + GetNodesDistance(curNode, aroundNodes[i]);if (newCostG <= aroundNodes[i].costG || !openList.Contains(aroundNodes[i])){//刷新赋值aroundNodes[i].costG = newCostG;//H:从当前位置到⽬标位置的移动步数aroundNodes[i].costH = GetNodesDistance(aroundNodes[i], endNode);//设置上级节点aroundNodes[i].lastNode = curNode;//添加到计算范围内if (!openList.Contains(aroundNodes[i])){openList.Add(aroundNodes[i]);}}}}}return null;}//计算距离int GetNodesDistance(AStarNode startNode, AStarNode endNode){return Mathf.Abs(startNode.pos.x - endNode.pos.x) + Mathf.Abs(startNode.pos.y - endNode.pos.y);}//周围节点只取上下左右四个, 不取对⾓线(根据实际需求设置周围节点)Vector2Int[] aroundPos = { new Vector2Int(0, 1), new Vector2Int(0, -1), new Vector2Int(1, 0), new Vector2Int(-1, 0) }; //获取周围NodeList<AStarNode> tmpAroundList = new List<AStarNode>();List<AStarNode> GetAroundNodes(AStarNode curNode, AStarNode[,] allNodes){tmpAroundList.Clear();for (int i = 0; i < aroundPos.Length; i++){//计算周围节点坐标int x = curNode.pos.x + aroundPos[i].x;int y = curNode.pos.y + aroundPos[i].y;//剔除不在取值范围内的数据if (x >= 0 && x < allNodes.GetLength(0) && y >= 0 && y < allNodes.GetLength(1)){if (allNodes[x, y] != null)tmpAroundList.Add(allNodes[x, y]);}}return tmpAroundList;}//获取路径(包含起点)List<AStarNode> tmpNodePath = new List<AStarNode>();List<AStarNode> GetPathWithNode(AStarNode startNode, AStarNode endNode){tmpNodePath.Clear();if (endNode != null){//逆向查找路径AStarNode temp = endNode;while (temp != startNode){tmpNodePath.Add(temp);temp = stNode;}tmpNodePath.Add(startNode);//路径数据反向tmpNodePath.Reverse();}return tmpNodePath;}#endregion}public class AStarNode{//A*算法节点类//是否能通过public bool isWall;//位置坐标public Vector2Int pos;//上个节点public AStarNode lastNode;//从起点到当前位置的移动步数public int costG;//从当前位置到⽬标位置的移动步数public int costH;//从起点到⽬标点的移动步数public int CostF{get { return costG + costH; }}public AStarNode(bool _isWall, Vector2Int _pos) {isWall = _isWall;pos = _pos;}//重写Equalspublic override bool Equals(object obj){if (obj is AStarNode){AStarNode objNode = (AStarNode)obj;return objNode.pos == pos;}return false;}public override int GetHashCode(){return base.GetHashCode();}}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Unity 的A-Star 算法在游戏中的具体实现
寻路算法在游戏开发中有着广泛的应用,广泛应用的寻路算法有三种:迪杰斯特拉算法、A-Star算法、BFS。
迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,
因此又叫狄克斯特拉算法。
是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题。
迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止广泛应用于单源最短路径问题上。
A-Star 搜寻算法俗称A星算法。
A-Star 算法是比较流行的启发式搜索算法之一,被广
泛应用于路径优化领域。
它的独特之处是检查最短路径中每个可能的节点时引入了全局信息,对当前节点距终点的距离做出估计,并作为评价该节点处于最短路线上的可能性的量度。
BFS(Bi-Directional Breadth-First-Search)双向广度优先搜索算法,数据结构的书中对此有详细的介绍。
在这三种算法中A-Star 算法在游戏开发中使用最为广泛。
这里主要介绍的就是A-Star 算法在游戏开发中的实际应用。
AStar 算法思想
A* 搜索算法结合了基于广度搜索的迪杰斯特拉算法的BFS 最佳优先搜索优点的最短路径算法。
其思想是将节点的邻近节点加入带处理的队列中,通过某个评估函数,依据函数有优先级的对处理队列中的节点进行评估。
公式表示为:F(n)=G(n)+H(n)。
其中F(n) 是从初始状态经由状态n 到目标状态的代价估计,G(n) 是某个状态空间中从开始的状态到状态n 实际所要付出的代价,(n) 从状态n 到目标状态的最优路径估计的代价。
实际使用当中在地图当中找到所需的目标节点。
首先要将节点分为四类:可通过节点、不可通过节点、开始节点、目标节点。
两种队列:开启队列(open-list)、关闭队列(close-list)。
开启队列的内容:开启队列里面是一些可能构成最短路径的节点。
算法运行过程中会对里面的节点进行维护,从开启队列中找到最短路径所需的节点。
关闭队列的内容:不需要考虑的节点不构成A-Star 算法可能选取的最短路径的节点。
算法开始时先从open-list 中找到 F
值最小的点,并且将其作为当前节点。
评估当前节点周围的节点,如果在open-list 中且通过当前点G值更小,则更新这个节点的G 和F 值。
如果周围节点在关闭列表中则不考虑。
把当前点从开启队列移除加入到关闭队列中。
目标节点加入到关闭列表的时候算法停止。
在算法进行时保存好路径,从目标点开始反向遍历到起始点。
记录好路径,这样就实现了从开始节点到目标节点的最优寻路。
在游戏开发中使用A-Star 算法
在使用Unity 游戏引擎实际开发的《Treasure-Hunt》游戏就使用了A-Star 算法来进行寻路。
游戏有四种节点:数字节点、障碍物节点、奖励节点、怪物节点。
除了数字节点和奖励节点可以直接通过外,其他的节点都是属于不可直接通过的节点。
用户点击屏幕上的节点,游戏人物可以沿着上下左右斜八个方向自动寻路避开所有的障碍物走到目标点,如果目标节点不可直接接近,则停在某个障碍物节点周围的节点。
在本游戏中具体用A-Star 实现寻路步骤为:
1: 定义节点类,每个节点类包含F 值G 值与H 值,并且包含其父节点作为属性以便保存寻路的路径。
2: 将游戏中的实际地图抽象为虚拟的逻辑地图,分别用不同的字符表示不同的节点,以曼哈顿距离来具体量化F、G、H 值。
3:对开启列表中的节点按照F 值进行排序,取出其最小值作为当前点并且从开启列表中移除,并且标记为访问过。
遍历八个方向并且继续循环上述操作。
节点可通过且不在开启列表则加入开启列表。
4: 当前点为目标点,或者当开启列表中元素为0 时则算法结束。
5: 遍历整个地图将所有标记过访问过的节点加入路径列表中,反转列表如果列表的元素个数大于二,并且起始节点与目标节点小于某个阈值的时候,则判定为有最优路径,其最优到达路径就是路径列表中的元素。
如若不是则没有到达的最优路径,也就是说目标点时不可到达点。