大家好,这次给大家分享最近学习A* 这款插件的心得,前面我一点点介绍,到最终我们实现一个多个小队寻路的效果。
首先介绍下怎么样使用这个插件,下载插件后导入unity,新建个地面和障碍物,分别把Layer命名为Ground和Obstacles。在建议一个空物体,命名为A*,单击Component-Pathfinding-Pathfinder 就可以看见Inspector面板出现了一个AstarPath,包含Graphs ,Settings,Save&load,Optimization和About 5个部分。 点击Graphs,添加一个新的Graph,这里就是添加我们的导航图。这里有很多种类型,我们往后一个个介绍,先创建一个基于单元的导航图,单击Grid Graph,会生成一个width*depth的规则网格,将NodeSize设置1,表示节点之间的间距为1个单位,将Center的坐标设置为(0,-0.1,0)因为我们的地面y=0,如果GridGraph的y也为0,在投射射到平面时候,可能会产生浮点误差,所以我们稍微下降一点高度。然后是CollisionTesting 碰撞测试选项里面,改变Mask的值,我们不希望AI在Obstacles层移动,所以设置Mask设置Obstacles层就可以了。接着是HeightTesting 高度测试,我们让射线的长度为100,Mask设置Ground层,就是只在Ground层进行投射,最后点击最下方的Scan,就可以看到生成的网格了。
下一步,我们添加一个角色,把一个带动画的人物拖入场景,首先添加角色碰撞器,调整好属性,选中人物,点击Component-Pathfinding-Seeker 为角色添加seeker脚本,使角色能够感知A*寻路,然后我们在创建一个移动脚本,让角色能够移动。为角色添加AstarAI.cs 脚本,
```using UnityEngine;
using System.Collections;
using Pathfinding;
public class AstartAI : MonoBehaviour {
//目标位置
public Transform targetPosition;
//声明一个seeker类的对象
private Seeker seeker;
private CharacterController controller;
//一个path类的对象。表示路径
public Path path;
//角色每秒的速度
public float speed = 100;
//当角色与一个航点的距离小于这个值时,角色便可转向路径上的下一个航点
public float nextWaypointDistance = 3;
//角色正朝其行进的航点
private int currentWaypoint = 0;
void Start()
{
//获得对Seeker组件的引用
seeker = GetComponent();
controller = GetComponent();
//注册回调函数,在AstartPath完成寻路后调用该函数。
seeker.pathCallback += OnPathComplete;
//调用StartPath函数,开始到目标的寻路
seeker.StartPath(transform.position, targetPosition.position);
}
private int turnSpeed = 100;
void FixedUpdate()
{
if (path == null)
{
return;
}
//如果当前路点编号大于这条路径上路点的总和,那么已经到达路径的终点
if (currentWaypoint >= path.vectorPath.Count)
{
Debug.Log("EndOfPathReached");
return;
}
//计算出去往当前路点所需的行走方向和距离,控制角色移动
Vector3 dir = (path.vectorPath[currentWaypoint] - transform.position).normalized;
dir *= speed*Time.fixedDeltaTime;
controller.SimpleMove(dir);
//角色转向目标
Quaternion targetRotation=Quaternion.LookRotation(dir);
transform.rotation=Quaternion.Slerp(transform.rotation,targetRotation,Time.deltaTime*turnSpeed);
//如果当前位置与当前路点的距离小于一个给定值,可以转向下一个路点
if (Vector3.Distance(transform.position, path.vectorPath[currentWaypoint]) < nextWaypointDistance)
{
currentWaypoint++;
return;
}
}
//当寻路结束后调用这个函数
public void OnPathComplete(Path p)
{
Debug.Log("FindThePath"+p.error);
//如果找到了一条路径,保存下来,并且把第一个路点设置为当前路点
if (!p.error)
{
path = p;
currentWaypoint = 0;
}
}
void OnDisable()
{
seeker.pathCallback -= OnPathComplete;
}
}
```
然后在新建一个小球,用来表示TargetPosition位置,小球放到我们想要移动到最终的目的地,然后拖到TargetPosition上,最后我们运行场景,就可以看到我们的人物绕过障碍物进行移动了,如果需要角色移动的平滑些,可以通过Component-Pathfinding-Modifiers添加,里面有很多种平滑脚本,我们选中SimpleSmooth 添加到角色上,然后慢慢调整参数,就可以看到角色不同程度的平滑移动了。最后,提供工程,运行Test1场景就行了。
网友评论