博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Unity3D行为树插件Behave学习笔记
阅读量:6155 次
发布时间:2019-06-21

本文共 12450 字,大约阅读时间需要 41 分钟。

Behave1.4行为树插件

下载地址:

安装插件和使用

我们先来看看插件的安装和基本使用方法,新建一个Unity3D项目,这里我使用的是5.0以上的版本:

导入插件

第一步当然是导入下载好的插件包了,操作略过...

创建资源

首先我们创建一个名为BT的文件夹,点击Project面板的create来创建相应的资源:

我们会在Asset目录下生成一个NewBehaveLibrary0.asset的文件,我们重命名为MyBehaveLibrary后将其拖入新建的BT文件夹中即可。

编辑资源

我们选中创建的资源,在Inspector中可以看到如下的界面:

我们点击Edit library后会弹出两个窗口,需要注意的是有一个窗口被另一个完全覆盖了,拖拽一下就可以看到了。点击behave browse面板的create创建一个collection,再点击一次create创建一个tree我们就有了一个行为树了。

接下来我们选中新创建的NewTree1在behave editor面板就可以编辑这个行为树了。

我们将面板下方的Action拖拽到面板中并在Inspector修改该节点的名称为MyAction:

接下来我们在顶部中间的方块拉出一条线,连线到我们的MyAction顶上,这样就把这个节点添加到该行为树上了。

好了到目前为止,我们的编辑就算是完成了。

编译资源

到目前为止,我们的资源还不能在项目中直接使用,我们需要先对其进行编译,选中我们的library,在Inspector中会出现选项:

我们点击一下Build library debug就可以编译出在项目中可以使用的资源了,如下:

编辑代码

编辑完成后,接下来我们该怎么使用行为树呢?看官们请接着看。

首先我们创建一个类Demo1Agent:

1 using Behave.Runtime; 2 using UnityEngine; 3 using System.Collections; 4 using Tree = Behave.Runtime.Tree; 5  6 public class Demo1Agent : IAgent { 7  8     public void Reset (Tree sender) { 9 10     }11     12     public int SelectTopPriority (Tree sender, params int[] IDs) {13         return 0;14     }15     16     public BehaveResult Tick (Tree sender, bool init) {17         Debug.Log("调用系统的Tick方法");18         return BehaveResult.Success;19     }20 21     public BehaveResult TickMyActionAction(Tree sender) {22         Debug.Log("我的action");23         return BehaveResult.Success;24     }25 }

我们创建了一个实现了IAgent的类,这个类会和一个行为树进行绑定,这里需要注意的是Tick和TickMyActionAction方法,在一个行为树中,同一时刻只有一个节点会执行,而我们的“MyAction”执行时,会寻找TickMyActionAction方法进行调用,这里的方法命名有一个规则:“Tick”+节点名称+“Action”,如果行为树找到了对应当前节点名称的方法就会进行调用,否则会调用Tick方法。

接下来我们创建一个类Demo1:

1 using UnityEngine; 2 using System.Collections; 3 using Behave.Runtime; 4 using Tree = Behave.Runtime.Tree; 5  6 public class Demo1 : MonoBehaviour { 7  8     Tree m_Tree; 9     Demo1Agent agent;10 11     void Start () {12         agent = new Demo1Agent ();13         m_Tree = BLMyBehaveLibrary.InstantiateTree(BLMyBehaveLibrary.TreeType.NewCollection1_NewTree1, agent);14     }15 16     void Update () {17         m_Tree.Tick();18     }19 }

这个类就比较简单了,我们通过BLMyBehaveLibrary创建一个和Demo1Agent的实例绑定的行为树,其中BLMyBehaveLibrary和NewCollection1_NewTree1都是我们之前编辑好编译生成的行为树代码,每帧调用行为树的Tick方法即可。

调试行为树

我们在场景中添加一个GameObject并绑定Demo1即可,运行就可以看到“我的Action”的输出了。

节点详解

目前behave提供了下面6个节点,我们来具体的看看:

Action

动作节点,执行核心逻辑的节点,该节点我们之前已经使用过了,主要用来实现我们需要的逻辑功能。

这里主要说一下Tick方法的3个返回值:

1 namespace Behave.Runtime2 {3     public enum BehaveResult4     {5         Running,6         Success,7         Failure8     }9 }
  • Running表示当前节点需要继续运行,下一次Tick时仍然会执行该节点。
  • Success表示节点执行完毕,而且执行成功。
  • Failure表示节点执行完毕,而且执行失败。

Decorator

装饰节点只会有一个子节点,作用为通过判断来控制是否执行其子节点,我们来看看装饰节点的使用方法:

首先我们创建一个新的行为树,并添加一个装饰节点和一个动作节点:

我们新建一个Demo2Agent:

1 using Behave.Runtime; 2 using UnityEngine; 3 using System.Collections; 4 using Tree = Behave.Runtime.Tree; 5  6 public class Demo2Agent : IAgent { 7  8     private bool _shoulDo; 9 10     public void Reset (Tree sender) {11         12     }13     14     public int SelectTopPriority (Tree sender, params int[] IDs) {15         return 0;16     }17     18     public BehaveResult Tick (Tree sender, bool init) {19         Debug.Log("调用系统的Tick方法");20         return BehaveResult.Success;21     }22 23     public BehaveResult TickMyDecoratorDecorator(Tree sender) {24         _shoulDo = !_shoulDo;25         if (_shoulDo) {26             Debug.Log("执行子节点");27             return BehaveResult.Success;28         } else {29             Debug.Log("不执行子节点");30             return BehaveResult.Failure;31         }32     }33 34     public BehaveResult TickMyActionAction(Tree sender) {35         Debug.Log("我的action");36         return BehaveResult.Success;37     }38 }

这里要注意的是,装饰节点的命名为:“Tick”+节点名称+“Decorator”,不是Action了。

接下来编译我们的行为树,添加一个类Demo2:

1 using UnityEngine; 2 using System.Collections; 3 using Behave.Runtime; 4 using Tree = Behave.Runtime.Tree; 5  6 public class Demo2 : MonoBehaviour { 7  8     Tree m_Tree; 9     Demo2Agent agent;10     11     void Start () {12         agent = new Demo2Agent ();13         m_Tree = BLMyBehaveLibrary.InstantiateTree(BLMyBehaveLibrary.TreeType.NewCollection1_NewTree2, agent);14     }15     16     void Update () {17         m_Tree.Tick();18     }19 }

添加到场景就可以查看效果了。

Sequence

顺序节点会让连接它的子节点从左到右依次执行,  每个节点从底部的线决定了顺序,摆放的位置无关紧要,如果第一个子节点返回失败,则整个节点返回失败。如果该子节点返回成功,则会自动往右边一个子节点执行,如果该节点返回runing,则会重新开始运行。

我们创建一个新的行为树,如下:

我们新建一个Demo3Agent:

1 using Behave.Runtime; 2 using UnityEngine; 3 using System.Collections; 4 using Tree = Behave.Runtime.Tree; 5  6 public class Demo3Agent : IAgent { 7  8     public GameObject cube; 9     public float time;10 11     float nowTime = 0;12 13     public void Reset (Tree sender) {14         15     }16     17     public int SelectTopPriority (Tree sender, params int[] IDs) {18         return 0;19     }20     21     public BehaveResult Tick (Tree sender, bool init) {22         Debug.Log("调用系统的Tick方法");23         return BehaveResult.Success;24     }25 26     public BehaveResult TickMyAction1Action(Tree sender) {27         Debug.Log("我的action1");28         if (cube.transform.position.x >= 3.0f) {29             cube.transform.position = new Vector3(3.0f, 0, 0);30             return BehaveResult.Success;31         }32         cube.transform.Translate(new Vector3(2.0f * time, 0, 0));33         return BehaveResult.Running;34     }35 36     public BehaveResult TickMyAction2Action(Tree sender) {37         Debug.Log("我的action2");38         if (nowTime >= 1.0f) {39             nowTime = 0;40             cube.transform.localEulerAngles = new Vector3(0, 0, 0);41             return BehaveResult.Success;42         }43         cube.transform.Rotate(new Vector3(360.0f * time, 0, 0));44         nowTime += time;45         return BehaveResult.Running;46     }47 48     public BehaveResult TickMyAction3Action(Tree sender) {49         Debug.Log("我的action3");50         if (cube.transform.position.x <= 0) {51             cube.transform.position = new Vector3(0, 0, 0);52             return BehaveResult.Success;53         }54         cube.transform.Translate(new Vector3(-2.0f * time, 0, 0));55         return BehaveResult.Running;56     }57 }

我们再创建一个Demo3:

1 using UnityEngine; 2 using System.Collections; 3 using Behave.Runtime; 4 using Tree = Behave.Runtime.Tree; 5  6 public class Demo3 : MonoBehaviour { 7  8     public GameObject cube; 9 10     Tree m_Tree;11     Demo3Agent agent;12     13     void Start () {14         agent = new Demo3Agent ();15         agent.cube = cube;16         m_Tree = BLMyBehaveLibrary.InstantiateTree(BLMyBehaveLibrary.TreeType.NewCollection1_NewTree3, agent);17     }18     19     void Update () {20         agent.time = Time.deltaTime;21         m_Tree.Tick();22     }23 }

我们在场景里添加一个Cube,把Demo3拖入并绑定Cube就可以查看效果了;

这里的效果是Cube先向前移动,然后旋转一下再向后移动,如此反复。

Selector

选择节点子节点会从左到右依次执行,和顺序节点不同的是,选择节点的子节点返回成功,则整个节点返回成功,如果子节点返回失败,则运行右边的一个子节点,并继续运行,一直到运行到子节点的末尾一个,则返回失败,下一次选择节点再被触发的时候,又从最左边 第一个节点开始运行。

我们创建一个新的行为树,如下:

我们新建一个Demo4Agent:

1 using Behave.Runtime; 2 using UnityEngine; 3 using System.Collections; 4 using Tree = Behave.Runtime.Tree; 5  6 public class Demo4Agent : IAgent { 7  8     public GameObject cube; 9     public float time;10     11     float nowTime = 0;12 13     public void Reset (Tree sender) {14         15     }16     17     public int SelectTopPriority (Tree sender, params int[] IDs) {18         return 0;19     }20     21     public BehaveResult Tick (Tree sender, bool init) {22         Debug.Log("调用系统的Tick方法");23         return BehaveResult.Success;24     }25 26     public BehaveResult TickMyAction1Action(Tree sender) {27         Debug.Log("我的action1");28         if (nowTime >= 1.0f) {29             nowTime = 0;30             cube.transform.position = new Vector3(0, 0, 0);31             //失败则执行下一个节点32             if (Random.value > 0.5f) {33                 return BehaveResult.Failure;34             }35             return BehaveResult.Success;36         }37         cube.transform.Translate(new Vector3(2.0f * time, 0, 0));38         nowTime += time;39         return BehaveResult.Running;40     }41     42     public BehaveResult TickMyAction2Action(Tree sender) {43         Debug.Log("我的action2");44         if (nowTime >= 1.0f) {45             nowTime = 0;46             cube.transform.localEulerAngles = new Vector3(0, 0, 0);47             //失败则执行下一个节点48             if (Random.value > 0.5f) {49                 return BehaveResult.Failure;50             }51             return BehaveResult.Success;52         }53         cube.transform.Rotate(new Vector3(360.0f * time, 0, 0));54         nowTime += time;55         return BehaveResult.Running;56     }57     58     public BehaveResult TickMyAction3Action(Tree sender) {59         Debug.Log("我的action3");60         if (nowTime >= 1.0f) {61             nowTime = 0;62             cube.transform.localScale = new Vector3(1, 1, 1);63             //失败则执行下一个节点64             if (Random.value > 0.5f) {65                 return BehaveResult.Failure;66             }67             return BehaveResult.Success;68         }69         cube.transform.localScale = new Vector3(nowTime, nowTime, nowTime);70         nowTime += time;71         return BehaveResult.Running;72     }73 }

我们再创建一个Demo4:

1 using UnityEngine; 2 using System.Collections; 3 using Behave.Runtime; 4 using Tree = Behave.Runtime.Tree; 5  6 public class Demo4 : MonoBehaviour { 7  8     public GameObject cube; 9     10     Tree m_Tree;11     Demo4Agent agent;12     13     void Start () {14         agent = new Demo4Agent ();15         agent.cube = cube;16         m_Tree = BLMyBehaveLibrary.InstantiateTree(BLMyBehaveLibrary.TreeType.NewCollection1_NewTree4, agent);17     }18     19     void Update () {20         agent.time = Time.deltaTime;21         m_Tree.Tick();22     }23 }

我们的小正方形会先运行Action1,然后有50%的机会进入Action2,进入Action2后又有50%的机会进入Action3。

Parallel

并行节点会从左到右触发它所有的子节点工作,对于并行节点有两个重要的设置,一个是子节点完成,一个是组件完成,子节点完成参数决定了子节点的返回值该如何处理:

  1. 如果并行节点设置为成功或者失败,那么无论它返回的是成功还是失败,子节点的输出都标记为完成。
  2. 如果并行节点设置为成功,那么子节点的输出只在返回成功时候才标记为完成。在触发所有的子节点工作后,一个子节点返回失败就会让整个并行组件返回失败。
  3. 并行节点设置为失败的话也会同理,子节点只有在返回完成时,它才会返回失败。

我们创建一个新的行为树,如下:

选择并行节点可以看到属性:

这里的意思是:所有的子节点都返回成功则退出该节点。

我们新建一个Demo5Agent:

1 using Behave.Runtime; 2 using UnityEngine; 3 using System.Collections; 4 using Tree = Behave.Runtime.Tree; 5  6 public class Demo5Agent : IAgent { 7  8     public GameObject cube; 9     public float time;10     11     float nowTime = 0;12 13     public void Reset (Tree sender) {14         15     }16     17     public int SelectTopPriority (Tree sender, params int[] IDs) {18         return 0;19     }20     21     public BehaveResult Tick (Tree sender, bool init) {22         Debug.Log("调用系统的Tick方法");23         return BehaveResult.Success;24     }25 26     public BehaveResult TickMyAction1Action(Tree sender) {27         Debug.Log("我的action1");28         if (cube.transform.position.x >= 3.0f) {29             cube.transform.position = new Vector3(3.0f, 0, 0);30             return BehaveResult.Success;31         }32         cube.transform.Translate(new Vector3(2.0f * time, 0, 0));33         return BehaveResult.Running;34     }35     36     public BehaveResult TickMyAction2Action(Tree sender) {37         Debug.Log("我的action2");38         if (nowTime >= 1.0f) {39             nowTime = 0;40             cube.transform.localEulerAngles = new Vector3(0, 0, 0);41             return BehaveResult.Success;42         }43         cube.transform.Rotate(new Vector3(360.0f * time, 0, 0));44         nowTime += time;45         return BehaveResult.Running;46     }47     48     public BehaveResult TickMyAction3Action(Tree sender) {49         Debug.Log("我的action3");50         if (cube.transform.position.x <= 0) {51             cube.transform.position = new Vector3(0, 0, 0);52             return BehaveResult.Success;53         }54         cube.transform.Translate(new Vector3(-2.0f * time, 0, 0));55         return BehaveResult.Running;56     }57 }

我们再创建一个Demo5:

1 using UnityEngine; 2 using System.Collections; 3 using Behave.Runtime; 4 using Tree = Behave.Runtime.Tree; 5  6 public class Demo5 : MonoBehaviour { 7  8     public GameObject cube; 9     10     Tree m_Tree;11     Demo5Agent agent;12     13     void Start () {14         agent = new Demo5Agent ();15         agent.cube = cube;16         m_Tree = BLMyBehaveLibrary.InstantiateTree(BLMyBehaveLibrary.TreeType.NewCollection1_NewTree5, agent);17     }18     19     void Update () {20         agent.time = Time.deltaTime;21         m_Tree.Tick();22     }23 }

运行游戏:会看见小正方形会旋转着前进,因为并行是所有子节点每帧都会被调用到,当两个子节点都返回成功时退出该节点。小正方形恢复到原点。

工程下载

转载地址:http://svifa.baihongyu.com/

你可能感兴趣的文章
centos64i386下apache 403没有权限访问。
查看>>
jquery用法大全
查看>>
PC-BSD 9.2 发布,基于 FreeBSD 9.2
查看>>
css斜线
查看>>
Windows phone 8 学习笔记(3) 通信
查看>>
Revit API找到风管穿过的墙(当前文档和链接文档)
查看>>
Scroll Depth – 衡量页面滚动的 Google 分析插件
查看>>
Windows 8.1 应用再出发 - 视图状态的更新
查看>>
自己制作交叉编译工具链
查看>>
Qt Style Sheet实践(四):行文本编辑框QLineEdit及自动补全
查看>>
[物理学与PDEs]第3章习题1 只有一个非零分量的磁场
查看>>
深入浅出NodeJS——数据通信,NET模块运行机制
查看>>
onInterceptTouchEvent和onTouchEvent调用时序
查看>>
android防止内存溢出浅析
查看>>
4.3.3版本之引擎bug
查看>>
SQL Server表分区详解
查看>>
使用FMDB最新v2.3版本教程
查看>>
STM32启动过程--启动文件--分析
查看>>
垂死挣扎还是涅槃重生 -- Delphi XE5 公布会归来感想
查看>>
淘宝的几个架构图
查看>>