将Behavior插件和AStarPathFinding插件结合
来源:互联网 发布:素质测评软件 编辑:程序博客网 时间:2024/06/02 01:59
在上一篇博文中,简单写了一个A*插件的简单移动和动态生成网格,可以看到,在那里,有一个StarPath方法一直没有使用,那是因为我故意留给行为树这里用的哈哈,接下来把代码改一改,把没必要的代码注释掉,我们把这个脚本封装起来,以后只提供给其他脚本实现寻路。AStar.cs 脚本代码如下:
using System.Collections;using System.Collections.Generic;using UnityEngine;using Pathfinding;public class AStar : MonoBehaviour { // public Transform target; private Seeker seeker; private CharacterController characterController; public Path path; private float speed = 100; private float angularSpeed = 10; private float nextWaypointDistance = 1.5f; private int currentWaypoint = 0; void Start () { } public void StarPath(Transform target) { seeker = GetComponent<Seeker>(); characterController = GetComponent<CharacterController>(); seeker.pathCallback += OnPathComplete; //寻路的一个回调 seeker.StartPath(transform.position, target.position, OnPathComplete); } private void FixedUpdate() { Move(); } public void Move() { if (path == null) //如果路径为空,直接返回 { return; } if (currentWaypoint >= path.vectorPath.Count) { return; } if (characterController != null && characterController.enabled == true) { Vector3 dir = (path.vectorPath[currentWaypoint] - transform.position).normalized; dir *= speed * Time.deltaTime; characterController.SimpleMove(dir); Quaternion targetRotation = Quaternion.LookRotation(dir); transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.fixedDeltaTime * angularSpeed); if (Vector3.Distance(transform.position, path.vectorPath[currentWaypoint]) < nextWaypointDistance) { currentWaypoint++; return; } } } public void OnPathComplete(Path p) { if (!p.error) { path = p; //如果不发生错误,把p传给path currentWaypoint = 0; } } private void OnDisable() { seeker.pathCallback -= OnPathComplete; } //提供get set方法供其他脚本使用 #region GetSet public float Speed { get { return speed; } set { speed = value; } } public float AngularSpeed { get { return angularSpeed; } set { angularSpeed = value; } } public float ArriveDistance { get { return nextWaypointDistance; } set { nextWaypointDistance = value; } } #endregion}
一定要记得加头文件!一定要记得加头文件!一定要记得加头文件!一定要记得加头文件!一定要记得加头文件!
这部分代码仅供寻路移动使用。接下来,我们开始准备行为树的部分。首先导入BehaviorDesigner.1.5.7.unitypackage和Behavior Designer - Movement Pack v1.5.2.unitypackage。这两个包,前一个是基础包,后一个是行为树移动的包。大家可以去官网下载,如果只是学习使用,也可以去网上找一下资源包。导入后,选择我们的角色,点击Unity上面的Tools->Behavior Designer->Editor。
然后会出现一个灰色面板,我们鼠标右键Add Behavior Tree或者点击上面的那个+号添加我们的行为树。(这里只简单实现A*和行为树的结合,不再对行为树进行详细的讲解,网上也有很多大神详细的讲了,有兴趣可以自行百度。)。添加后,我们来自己写一个巡逻过程。我们先看看自带的巡逻是怎么样的。
先添加上巡逻任务,然后单击这个任务图标,可以看到巡逻的一系列信息。图片如下:
Speed是巡逻的速度,然后是旋转速度,以及距离目标点多远算抵达。后面的Stop On Task End如果选中了,则会在巡逻后停止。Waypoint Pause Duration则表示到达一个目标点之后停留多久。 Waypoints这里可以设置巡逻点个数,以及巡逻点的位置。我们参照自带的自己写一个巡逻MyPatrol.cs
using System.Collections;using System.Collections.Generic;using UnityEngine;using BehaviorDesigner.Runtime.Tasks;using BehaviorDesigner.Runtime;using Pathfinding;public class MyPatrol : Action { public SharedFloat speed; //行动的速度。 public SharedFloat angularSpeed; //旋转速度 public SharedFloat arriveDistance; //多远算到达目的地 public SharedBool stopOnTaskEnd; //需不需要在巡逻完所有的点后停止 public SharedFloat waypointPauseDuration; //巡逻到目标点后停留的间隙 public SharedGameObjectList waypoints; private bool isOverPatrol = false; private AStar aStar; public override void OnAwake() { aStar = GetComponent<AStar>(); if (aStar != null && aStar.enabled == true) { aStar.Speed = speed.Value; aStar.AngularSpeed = angularSpeed.Value; aStar.ArriveDistance = arriveDistance.Value; } } public override void OnStart() { StartCoroutine(_myPatrol()); //调用巡逻 } public override TaskStatus OnUpdate() { if (waypoints == null) //如果目标点为空,则返回失败 { Debug.LogError("No Set Waypoint!"); return TaskStatus.Failure; } if (stopOnTaskEnd.Value && isOverPatrol) //如果选择了巡逻完后停止,并且巡逻完毕了。返回true { return TaskStatus.Success; } return TaskStatus.Running; } IEnumerator _myPatrol() { if (stopOnTaskEnd.Value) //如果需要巡逻后停住 { foreach (GameObject item in waypoints.Value) //巡逻完所有的节点 { aStar.StarPath(item.transform); //设置一个目标点 while (true) { if (Vector3.Distance(transform.position, item.transform.position) <= arriveDistance.Value) { break; } yield return null; } yield return new WaitForSeconds(waypointPauseDuration.Value); //停留多少间隙 } isOverPatrol = true; //已经完成巡逻 yield return null; } else { while (true) //完成巡逻后重新设置对象 { foreach (GameObject item in waypoints.Value) { aStar.StarPath(item.transform); while (true) { if (Vector3.Distance(transform.position,item.transform.position) <= arriveDistance.Value) { break; } yield return null; } yield return new WaitForSeconds(waypointPauseDuration.Value); //停留多少间隙 } } } }}
这里主要是使用了IEnumerator实现了巡逻的主要逻辑。首先定义一些行为树自带的共享变量,这样就可以在各个脚本间引用一些值了,比如移动速度等。要注意的地方是:共享变量必须定义为publi,且要用.Value的形式才能引用出里面的值。比如public SharedFloat speed;想用speed必须是speed.Value才行。我们先将一些必要的变量定义好,然后写一个IEnumertor,里面分别针对巡逻完后是否需要停止写逻辑。如果需要停止,我们就遍历巡逻目标点waypoints这个List,首先用aStar.StarPath(item.transform)寻路并移动(注意:不能一直寻路移动,只需要执行一次就行了),然后用一个死循环判断目标点和自己的距离,如果小于arriveDistance则认为是到达了,到达了直接break跳出去寻路到下一个目标点。否则就yield return null跳过这一帧(这里一定要注意!这个死循环里判断,如果不满足一定要跳过这一帧,否则会在这一帧不停得判断,导致Unity卡死。这个地方卡了我好久)。还有种情况,巡逻完不需要停止,即反复巡逻,这里我们只需要把刚才那段复制进一个死循环即可,当目标点都走完了,我们再从第一个开始,继续巡逻。
就这样,我们就写了一个简单的小例子,有兴趣的朋友可以自己试试。
最后这里放上我们学习用的插件:
行为树插件 http://download.csdn.net/download/l1606468155/9923832
AStarPathfinding插件 http://download.csdn.net/download/l1606468155/9923826
- 将Behavior插件和AStarPathFinding插件结合
- Unity3D之AStarPathFinding插件的使用
- Unity3D之AStarPathFinding插件的使用
- Unity3D之AStarPathFinding插件的使用
- Unity3D之AStarPathFinding插件的使用
- [Unity插件]Behavior Designer
- unity插件Behavior designer
- [Unity插件]Behavior Designer:节点
- Mybatis插件原理和PageHelper结合实战分页插件
- myeclipse和其它插件结合demo
- spring-data-elasticsearch和shield插件结合
- Unity中的行为树插件:Behavior Designer
- [Unity插件]Behavior Designer:自定义Conditional节点
- [Unity插件]Behavior Designer:SharedVariable与GlobalVariable
- [Unity插件]Behavior Designer:制作敌人AI
- unity第三方插件behavior designer心得
- Unity中的行为树插件 Behavior Designer
- Unity中 Behavior Designer 行为树插件
- Deeplearning4j源码研习(1): BP算法原理及源码实现
- POJ 1067 取石子游戏 经典威佐夫博弈
- 《Spring+Mybatis企业应用实战》学习-1~3章
- LinkedHashMap
- 数据结构串的基本操作及KMP算法
- 将Behavior插件和AStarPathFinding插件结合
- Example3.12 Solving the Gridworld
- js多态直观理解
- 流行移动平台自动化框架逐项比拼
- vue2 开发问题整理
- ZOJ3872:Beauty of Array(浙江省赛2015)
- docker-代码的搬运工
- GCD
- USB选择PTP功能时,如何同时显示内置、外置SD卡内容