unity 贝塞尔曲线算法a星算法多久刷新一次

unity A星算法,Unity3D,游戏源码,6m5m游戏素材
请求处理中...
&unity A星算法,A*算法是2D游戏中最常用的一种算法,源码包含多个样例,非常的实用,c#脚本。
或 10 积分 ()
下载8浏览人数732交付方式直接下载
注意:【1】本站只是个免费分享平台,并不敢保证所有源码人人都能编译,因素太多,旨在学习研究,如果您有顾虑或斤斤计较就请不要下载了,大家都不容易,互相理解,才能让更多的好资源出现!【2】本站资源仅限于学习研究,请在下载后24小时内删除,不要用于任何商业用途。【3】部分素材压缩包因体积过大而上传到百度等网盘上,如果发现在本站下载的压缩包只要有几K大小,说明该压缩包里只是网盘的下载链接,并非文件损坏,本站的所有素材都是经过了审核,大家可放心下载,欢迎监督反馈。【4】做个好平台真心不容易,我们一直在努力,因本站素材量大,难免会出现某网盘下载链接失效等问题,请大家及时反馈,我们会及时修正保证您可以拿到素材,请大家支持和理解!
免责声明:本网所展示的素材与服务信息由买卖双方自行提供,其真实性、准确性和合法性由信息发布人负责。本网不提供任何保证,并不承担法律责任,如有不妥之处请及时反馈,本网将会妥善处理。
友情提醒:本站旨在游戏开发的学习,所分享的素材资源均来源于网络,仅适用于学习研究,禁止用于任何商业用途,否则后果自负,所展示的素材版权归原作者或公司所有,如果本站素材侵犯了您的权益,请与联系我们,我们将及时处理。
猜您喜欢的游戏素材
0金币 / 份
1金币 / 个
1金币 / 个
0金币 / 个
1金币 / 个
0金币 / 个
0金币 / 个
2金币 / 个
0金币 / 个
1金币 / 个
好评率100%unity3D(6)
原文地址:http://t-machine.org/index.php//debugging-a-pathfinding-in-unity/
说明:在文章中有时出现A星有时出现A*,都是一个东西,要是不理解,可以先看看原作者推荐的那几篇文章……
我的项目需要一个快速、高效、强大和适应性强的寻路系统。我的角色要飞、走、爬、瞬移穿过一个程序生成的陆地。完成这个要求有些复杂,但是过程却很有趣。
我想要一个模块,它能智能的引导障碍周围的怪物,并选择比较容易走的路,而不是从悬崖边走过去(反之亦然,比如巨型蜘蛛)。就像这样:
Unity Asset Store
Unity里要做任何事,访问Asset Store都应该是第一步。
我搜索排名靠前的几个寻路资源包,并且测试了有webPlayer或者免费版本的demo。
其中有些挺好,但是总的来说让人失望。性能不错,其中大部分都用了协程或者后台线程来控制CPU的使用,这很不错!(相对容易自己实现,话说这是A*的两大特性之一)
……但是用户接口很糟糕(我理解不了……)或者代码很难写,或者丢失了A星的核心元素的设置(比如动态边界dynamic edge:在游戏里使用A*的另一个原因)。
如果只是简单用用,它们很多都不错。24小时热卖资源里有一个看起来很好,由一个大团队维护——但是他们很精明(只能在你购买后才能看到文档!)而且看上去代码相对难写。
最后,我放弃了,于是我想:
也许……每个创新的游戏都需要你重新实现A*算法,来保证你的游戏独一无二的特点?
(A*不难实现,有很多选择方式,也许在这件事上重复造轮子是一件好事)。
A星是什么,如何工作?如何实现?
我推荐以下几篇文章:
— 很好理解
—很多人自己实现A*时都参考它
这几篇文章留给我们一个基本算法:
OPEN = priority queue containing START
CLOSED = empty set
while lowest rank in OPEN is not the GOAL:
current = remove lowest rank item from OPEN
add current to CLOSED
for neighbors of current:
cost = g(current) + movementcost(current, neighbor)
if neighbor in OPEN and cost less than g(neighbor):
remove neighbor from OPEN, because new path is better
if neighbor in CLOSED and cost less than g(neighbor): **
remove neighbor from CLOSED
if neighbor not in OPEN and neighbor not in CLOSED:
set g(neighbor) to cost
add neighbor to OPEN
set priority queue rank to g(neighbor) + h(neighbor)
set neighbor's parent to current
reconstruct reverse path from goal to start
by following parent pointers
在Unity里用C#实现
首先:Unity在使用C#语法时有些问题。泛泛的说,一些C#代码在Unity里会引起问题——最常见的例子:多维数组。你可以给Unity打补丁修复它,但是这么做不太常规。替代方法是简单粗暴的实现一个更底层的结构(很烂,但是实用)。
其次:微软C#/.NET标准库有一个内置的SortedList,我直说吧它名字起错了。你在每个位置只能有一个元素(这是sorted Map或者Set-sorted List,不是sorted List)。在我们的例子里这是一个错误的数据结构,虽然你可以通过定制它让它工作(让每个物品一个List,把节点从List移到另一个List)——哎呦,复杂!
还是一样:很烂,但是实用。我个人写了我自己的SortedList。
可能你游戏里已经有类似的结构了:
public class Node
public int x,
graph / grid类
举个例子:
public class Grid
public Node[] allN
public int nodesAcross, nodesD // needed to workaround Unity bugs
public Node NodeAt( int x, int y ) // needed to workaround Unity bugs
return allNodes[ x + y*nodesAcross];
public void SetNodeAt( int x, int y, Node n ) // needed to workaround Unity bugs
allNodes[ x + y*nodesAcross] =
写一个自己的SortedList
超简单,但是第一次写的时候我绕进去了,因为我不熟悉C#内部的foreach循环里如何保持整洁。我认为你也可能有类似的问题。对于A*你只需要一个包含以下方法的类:
public class MySortedList&T& where T: class
public MySortedList();
public int Count();
public T GetFirst();
public T RemoveFirst();
public void RemoveItem( T victimItem );
public bool Contains( T searchItem );
public int AddWithValue( T newItem, float newValue );
检查你的算法
这是一个数据敏感的算法,我们创建了一些数据结构(不太危险)和一个自定义的容器(恩,危险!容易出错)。
我强烈建议你给MySortedList写单元测试。我没有这么做(我还没找到一个适用于Unity的好的单元测试框架),而且很后悔。特别关注以下几点:
测试Contains方法是否正确测试Remove方法是否真的移除了对象
省略上面的任何一项,A星有可能陷入死循环,因为它持续添加节点到列表里。尤其是对Contains的测试,确保为你的自定义类实现了Equals和GetHashcode!
调试你的算法
现在到有趣的部分了,这是一个重度数据的算法:在真正的游戏中,它会处理成千上万的节点,以及数以万计的边界。调试它简直就是下地狱,千万别那么做啊。
你第一步的思考可能是:
我可以给调试A星弄个界面吗?这样调试它就变得又快又容易?
我的思路:
做个Calculate A Path的组件
把开始节点和结束节点放进去写一个编辑器类,增加一个按钮“Calculate Path”
A星输出一个Path对象Calculate A Path组件持有这个对象
创建一个新的GameObject把Path对象作为它的子对象给它附加一个PathVisualizer组件
PathVisualizer组件实现了OnGizmos()
在每个节点都绘制一个立方体在开始和结束节点的立方体和其他立方体颜色不同在节点之间通过线段连接
需要注意的事:
因为每个路径都附加到一个GameObject上,你可以微调一下你的A*实现,在编辑器里重新跑一下,对比一下输出的2条路径,看看是否符合你修改的初衷。
我不需要我的Nodes和Paths类继承MonoBehaviours,因为我创建了一个可视化behaviour,而不是保存了一个需要可视化的路径的引用。(我也没懂)
本文的第一张图就是我的第一版可视化寻路。
可视化图和代价
我同时也做了一些可视化地图的工作:
以及代价的可视化。我实现了“双重”的代价:下坡比上坡更容易,因此每个边界都有两种颜色,一种是上坡的代价,一种是下坡的代价:
编辑器优化
没有优化的情况下,你的A星算法在很短的时间内运行完,它可能要计算成千上万的节点,这是即时的。
但是,当你有bug时,A*会陷入死循环,Unity会卡住(Unity对于代码死循环基本没有什么措施)。
因此从实用性的角度讲,你会想把计算放到协程里,并且在出错时,在编辑器里显示一些信息。我计划添加一个进度条给Open和Close表,显示它们的容量。我知道节点的总数量,两个列表都不能超过节点的总数量,我可以这样显示:
编辑器里的协程
可悲的是,虽然Unity允许在编辑器里使用协程(Unity的员工在4.5里这样用过),你这样用却不行。
但是Unity实现协程很简单,自己写也很简单。使用你就可以自己做协程。
我也这样做了(把你自己的回调添加到update里,手动运行IEnumerator),但是我添加了一些东西重绘GUI(经常但是不频繁)和其他一些小的特性。
断言和异常
让我们回顾前文:
这是一个重度数据的算法:在真正的游戏中,它会处理成千上万的节点,以及数以万计的边界。调试它简直就是下地狱,千万别那么做啊。
断言(Assertions)是我们的朋友。许多牛b的游戏开发者都喜欢它,尤其是在控制台上(一些机器运行不起来单元测试,断言能帮你在这种机器上完成单元测试)。
我修改了代码的实现,增加了下面的断言:
从一个节点到另一个节点,代价不能是负的
这应该是不可能的,即使你想在游戏里实现点特别的东西,你也不可能想要这个结果因为A*会滥用这个,在你的“负”边界上来回跑一跑,会发现总的路径代价因为它们而减少你可能想要0代价的边界——比如一个传送点——但是小心:它们也可能引起无限循环的问题一般来讲当你读到一个边界代价&=0f时应该断言(Assert)
伪代码的核心循环的最后一行,把当前节点作为相邻节点的父节点。如果这个节点已经指向相邻节点了,就不要这么做!
再说一下:这个情况不会发生,如果算法正确,它就是绝对错误的(0或者负的代价会导致这个情况)更糟糕的是:一个链表里包含多个相同节点,这会在后面导致死循环我增加了一个断言:当给一个链表的末尾添加了一个节点,确保这个节点之前不在链表里
不要允许open表里的节点数超过总节点数
应该不可能!不能包含相同的节点!
close表也一样(我把close表用集合实现了,但是如果你的Equals方法有bug,用标准库里的set也不管用)
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:5062次
排名:千里之外
(1)(1)(3)(1)(3)Unity 2d A星(Astar)寻路实现 VR开发教程
寻路是游戏开发中的硬菜,必须过的一道坎。不过还好这种硬菜,牛人几百年前就做好了,不用我们亲自下厨了。如果你特别喜欢探究其精髓可以自行研究下,我是觉得自己没有能力在这么经典的算法上再优化什么了。
当然根据分析我们是不用再造轮子了 ,这篇实际是我将深蓝的右手的AStar实现移植到了& & 中,实现效果如下:
这里为了减小图片尺寸,我给质量调的有点低了
利用上篇的成果,我们可以很好的进行可视化调试了,有兴趣的朋友可以参照上篇
这里实现的难点列出下,
1、AStar 算法的障碍物矩阵长宽值,必须是2的平方数
2、AStar 算法是基于网格的所以需要构建网格(非Mesh)系统
2、Unity3d中的世界坐标和屏幕坐标的单位不同
3、也是最坑的,不要再Unity编辑模式下,缩放Game窗口(分辨率不足的情况),这样会使得屏幕坐标不准确
4、使用轮子的代码很简单这里我就不赘述了
当然代码中也有亮点的,比如以下代码我用UniRx 给Update中的Input鼠标点击事件给解耦出来了
void Awake()& {
&&&&ResetMatrix();
&&&&Observable.EveryUpdate().Where(_ =& Input.GetMouseButtonDown(0)).Subscribe(LeftMouseClick);
using UnityE
using System.C
using System.Collections.G
using UniRx;
using Components.AS
using Components.S
public class MainControl : MonoBehaviour {
&&&&private byte[,] Matrix = new byte[64, 64];
&&&&private float GridSize = 0.2f;
&&&&List lst = new List();
&&&&List lst2 = new List();
&&&&List lst3= new List();
&&&&List lst4 = new List();
&&&&private IPathFinder PathFinder = null;
&&&&private Point2D S
&&&&private Point2D E&
&&&&void Awake()& {
&&&&&&&&ResetMatrix();
&&&&&&&&Observable.EveryUpdate().Where(_ =& Input.GetMouseButtonDown(0)).Subscribe(LeftMouseClick);
&&&&private void LeftMouseClick(long l)
&&&&&&&&lst2.Clear();
&&&&&&&&Rect rect = new Rect();
&&&&&&&&rect.width = GridS
&&&&&&&&rect.height = GridS
&&&&&&&&rect.x = GridS
&&&&&&&&rect.y = GridS
&&&&&&&&lst2.Add(rect);
&&&&&&&&Start = new Point2D(1,1);
&&&&&&&&Vector3 p = Input.mouseP
&&&&&&&&int x = ((int)p.x / (int)(GridSize * 100));
&&&&&&&&int y = ((int)p.y / (int)(GridSize * 100));
&&&&&&&&End = new Point2D(x, y);&
&&&&&&&&Debug.Log(\&mouse:\& + p + \& x/GridSize:\& + x + \& y/GridSize:\&+y);
&&&&&&&&lst4.Clear();
&&&&&&&&lst4.Add(IndexConvertToRect(x,y));
&&&&&&&&PathFinder = new PathFinderFast(Matrix);
&&&&&&&&PathFinder.Formula = HeuristicFormula.M
&&&&&&&&PathFinder.SearchLimit = 2000;
&&&&&&&&List path = PathFinder.FindPath(Start, End);
&&&&&&&&if (path == null)
&&&&&&&&&&&&Debug.Log(\&路径不存在!\&);
&&&&&&&&else
&&&&&&&&&&&&string output = string.E
&&&&&&&&&&&&for (int i = path.Count - 1; i &= 0; i--)
&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&output = string.Format(output
&&&&&&&&&&&&&&&&&&&&+ \&{0}\&
&&&&&&&&&&&&&&&&&&&&+ path[i].X.ToString()
&&&&&&&&&&&&&&&&&&&&+ \&{1}\&
&&&&&&&&&&&&&&&&&&&&+ path[i].Y.ToString()
&&&&&&&&&&&&&&&&&&&&+ \&{2}\&,
&&&&&&&&&&&&&&&&&&&&\&(\&, \&,\&, \&) \&);
&&&&&&&&&&&&&&&&lst2.Add(IndexConvertToRect(path[i].X,path[i].Y));
&&&&&&&&&&&&}
&&&&&&&&&&&&Debug.Log(\&路径坐标分别为:\& + output);
&&&&&&&&&&&&&
&&&&private void ResetMatrix()
&&&&&&&&for (int y = 0; y & Matrix.GetUpperBound(1); y++)
&&&&&&&&&&&&for (int x = 0; x & Matrix.GetUpperBound(0); x++)
&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&Matrix[x, y] = 1;
&&&&&&&&&&&&&&&&Rect rectx = new Rect();
&&&&&&&&&&&&&&&&rectx.width = GridS
&&&&&&&&&&&&&&&&rectx.height = GridS
&&&&&&&&&&&&&&&&rectx.x =x* GridS
&&&&&&&&&&&&&&&&rectx.y =y* GridS
&&&&&&&&&&&&&&&&lst3.Add(rectx);
&&&&&&&&&&&&}
&&&&&&&&Rect rect = new Rect();
&&&&&&&&for (int i = 0; i & 18; i++)
&&&&&&&&&&&&
&&&&&&&&&&&&Matrix[i, 12] = 0;
&&&&&&&&&&&&rect = new Rect();
&&&&&&&&&&&&rect.width = GridS
&&&&&&&&&&&&rect.height = GridS
&&&&&&&&&&&&rect.x = i * GridS
&&&&&&&&&&&&rect.y = 12 * GridS
&&&&&&&&&&&&lst.Add(rect);
&&&&&&&&for (int i = 13; i & 17; i++)
&&&&&&&&&&&&Matrix[17, i] = 0;
&&&&&&&&&&&&&rect = new Rect();
&&&&&&&&&&&&rect.width = GridS
&&&&&&&&&&&&rect.height = GridS
&&&&&&&&&&&&rect.x = 17 * GridS
&&&&&&&&&&&&rect.y = i * GridS
&&&&&&&&&&&&lst.Add(rect);
&&&&&&&&for (int i = 3; i & 18; i++)
&&&&&&&&&&&&Matrix[i, 16] = 0;
&&&&&&&&&&&&&rect = new Rect();
&&&&&&&&&&&&rect.width = GridS
&&&&&&&&&&&&rect.height = GridS
&&&&&&&&&&&&rect.x = i * GridS
&&&&&&&&&&&&rect.y = 16 * GridS
&&&&&&&&&&&&lst.Add(rect);
&&&&void OnDrawGizmos()
&&&&&&&&lst.ForEach((r) =&
&&&&&&&&&&&&otherTest.DrawRect(r, Color.yellow);
&&&&&&&&});
&&&&&&&&lst2.ForEach((r) =&
&&&&&&&&&&&&otherTest.DrawRect(r, Color.red);
&&&&&&&&});
&&&&&&&&lst4.ForEach((r) =&
&&&&&&&&&&&&otherTest.DrawRect(r, Color.white);
&&&&&&&&});
&&&&public Rect IndexConvertToRect(int x, int y)
&&&&&&&&Rect rect2 = new Rect();
&&&&&&&&rect2.x = Convert.ToSingle(x * GridSize);
&&&&&&&&rect2.y = Convert.ToSingle(y * GridSize);
&&&&&&&&rect2.width = GridS
&&&&&&&&rect2.height = GridS
&&&&&&&&return rect2;
一步一个脚印前进吧。
这里是深蓝色右手的AStar算法代码,这里我给分解代入到了Unity中
<font color="#-28<font color="#-28<font color="#-22<font color="#-26<font color="#-26<font color="#-26<font color="#-23<font color="#-23<font color="#-21<font color="#-21
VR设计师和开发者们开始着手如何让VR环境及体验更加有趣、逼真。以下是一些关于如何为room...
笔者在为《幻想装置》和《工作模拟》制作出混合现实的预告片以后,研究了更深层次的VR...
关于用EasyAR SDK 搭建AR 开发环境的教程,我已经写过很多了,不懂得朋友可以看下我之...
一篇VR实践指导文章。重点关注的是将传统UX设计流程及方法融入VR产品设计的思路,以及...
产品设计实习生的总结。我越来越喜欢FB了,他们有社交,他们有VR,他们有John Carmack...}

我要回帖

更多关于 unity3d 自动寻路算法 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信