Astar寻路

2016-03-27  本文已影响159人  Moment__格调

大家好,这次给大家分享最近学习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场景就行了。  

上一篇下一篇

猜你喜欢

热点阅读