fish 发表于 2020-11-25 09:21

Unity寻路插件(A* Pathfinding)入门教程十三:2D中的寻路

本系列的教程文章基于 A*Pathfinding Project 4.2.8的官网教程翻译,每一章节的原文地址都会在教程最下方给出。
这篇教程将讲解怎么在2D游戏中寻路。
插件里一共提供了2个介绍2D寻路相关的场景。Example15_2D 和 Example16_RVO 2D。
创建一个2D游戏的寻路其实有很多种方法,下面这两种是比较常见的方式:
自顶至下(Top-down),大概就是俯视世界的一种方式,就是上面图片展示的方式。平台式寻路(Platformer),类似于马里奥。遗憾的是,目前这个插件尚不支持这种寻路……不过你可以使用很多的路点,然后创建一个自定义的连接(connections)去实现,但是这并不能通用。
这里有个视频,可以教你怎么使用寻路创建一个简单的2D场景。(爬墙)
Graph 支持

gird graph 和layered grid graph 可以很好的在XY面工作。实际上,grid graph也可以旋转到任何方向,并且它仍然能够正常工作。对于2D游戏来说,你应该勾选grid graph上的2D按钮,这样就会自动帮你旋转graph,与XY面成一条直线。如果你想用2D的碰撞,你也需要勾选Use 2D Physics 的按钮。Point graphs 也支持XY面的寻路。和gird类型的一样,如果你需要使用Raycast或者使用2D 的物理碰撞,也要勾选Use 2D Physics按钮。Recast graphs 也可以被旋转到XY平面,或者其他任何角度。但是他们并不支持2D的碰撞体,也不支持使用sprites作为栅格输入的处理。如果你用这场的网格是没有什么问题的。Navmesh graphs 的原理和 recast 类似。所以他们都支持任何角度的视角。但是你需要注意要保持 graphs的“up”和希望的“up”方向一致。比如,如果你想用navmesh在XY平面上工作,你需要将rotation字段设置到(-90,0,0),当然你不能简单的在may或者Blender软件里直接旋转mesh。
Graph 更新(Graph updates)

Navmesh Cutting
Navmesh 裁切可以用来更新2D或者任何其他方向的 navmesh 或者 recast类型的graph。但是要注意,navmesh cuts的旋转也要正确。navmesh cuts用一个2D的轮廓来表示,这些轮廓会投影在graph的表面。如果navmesh cut的旋转信息错误,那么它投影的方向就只有一条线,那么就不能正确的裁切graph。如下图:
当你使用一个非水平的Graph的时候,useRotationAndScale的选择框必须勾选上才能保证正常工作。
2D Colliders
当使用graph updates的时候,3D游戏中一个常用的做法就是:
var guo = new GraphUpdateObject(GetComponent<Collider>().bounds);
// change some settings on the object
AstarPath.active.UpdateGraphs(guo);但是在2D游戏中使用了 2D Colliders 的方式,上面的代码就会失效。原因是2D的Colliders可以认为是无限薄的,所以它的bounds的体积会是一个0。所以当要判定一个节点是否在某个边界(bounds)里的时候,那么永远不会命中,因为你没法在一个没有体积的物体里放进任何东西。解决这个问题的方式就是,扩展这个bounds的Z轴,让他能够包含所有的节点。
var bounds = GetComponent<Collider2D>().bounds;
// Expand the bounds along the Z axis
bounds.Expand(Vector3.forward*1000);
var guo = new GraphUpdateObject(bounds);
// change some settings on the object
AstarPath.active.UpdateGraphs(guo);移动脚本(Movement scripts)

AIPath支持Grid graphs、navmesh graphs、recast graphs类型的任意方向,它会自动检测方向。不过,你需要禁用gravity选项,以防止这些物体因为重力从map掉下来~而Point graphs没有定义“up”方向,所以AIPath就不知道怎么去定位方向了。如果你知道方向的话,你可以代码里设定变量来强迫AIPath寻路。
// In the AIPath.cs script, find the line that looks like
// movementPlane = graph != null ? graph.transform : GraphTransform.identityTransform;
// and replace it with
var graphRotation = new Vector3(-90, 0, 0);
movementPlane = new GraphTransform(Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(graphRotation), Vector3.one));
graphRotation 可以改变成任何你想要的方向。RichAI 暂时不支持除XZ平面上的其他方向。但是,我们已经做相当多的工作来让他支持,并且已经完工了,希望早点在下个版本里发布。AILerp 支持任何的graph方向。对于许多2D游戏来说,他们可能希望+Y轴为前方,而不是3D里常用的+Z轴。如果这样的话,你只需要勾选rotationIn2D选框。
局部回避(Local avoidance)

局部回避,在XY平面工作。你仅需要做一件事,就是改变movementPlane设置里的RVOSimulator组件到XY。可以查看插件的示例Example16_RVO 2D 来看他是怎么配置和运作的。
原文链接:
页: [1]
查看完整版本: Unity寻路插件(A* Pathfinding)入门教程十三:2D中的寻路