Unity3D行为树插件Behave学习笔记

Behave1.4行为树插件

下载地址:http://pan.baidu.com/s/1i4uuX0Ldom

安装插件和使用

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

导入插件

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

建立资源

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

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

编辑资源

咱们选中建立的资源,在Inspector中能够看到以下的界面:调试

咱们点击Edit library后会弹出两个窗口,须要注意的是有一个窗口被另外一个彻底覆盖了,拖拽一下就能够看到了。点击behave browse面板的create建立一个collection,再点击一次create建立一个tree咱们就有了一个行为树了。code

接下来咱们选中新建立的NewTree1在behave editor面板就能够编辑这个行为树了。orm

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

接下来咱们在顶部中间的方块拉出一条线,连线到咱们的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.Runtime
2 {
3     public enum BehaveResult
4     {
5         Running,
6         Success,
7         Failure
8     }
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://pan.baidu.com/s/1sjZNg9B

相关文章
相关标签/搜索