[Unity插件]Lua行为树(七):行为树嵌套

在上一篇的基础上,可以测试下行为树的嵌套,所谓的行为树嵌套,就是在一棵行为树下的某一个分支,接入另一棵行为树。

以下面这棵行为树为例:

 

TestBehaviorTree2.lua

 1 TestBehaviorTree2 = BTBehaviorTree:New();
 2 
 3 local this = TestBehaviorTree2;
 4 this.name = "TestBehaviorTree2";
 5 
 6 function this:New()
 7     local o = {};
 8     setmetatable(o, self);
 9     self.__index = self;    
10     self:Init();
11     return o;
12 end
13 
14 function this:Init()
15     local repeater = BTRepeater:New(2);
16     local sequence = BTSequence:New();
17     local log = BTLog:New("This is a other tree!!!");
18     local log2 = BTLog:New("This is a other tree 2!!!");
19 
20     self:SetStartTask(repeater);
21 
22     repeater:AddChild(sequence);
23 
24     sequence:AddChild(log);
25     sequence:AddChild(log2);
26 end

TestBehaviorTree.lua

 1 TestBehaviorTree = BTBehaviorTree:New();
 2 
 3 local this = TestBehaviorTree;
 4 this.name = "TestBehaviorTree";
 5 
 6 function this:New()
 7     local o = {};
 8     setmetatable(o, self);
 9     self.__index = self;    
10     self:Init();
11     return o;
12 end
13 
14 function this:Init()
15     local repeater = BTRepeater:New(2);
16     local selector = BTSelector:New();
17     local sequence = BTSequence:New();
18     local isNullOrEmpty = BTIsNullOrEmpty:New("123");
19     local log = BTLog:New("This is a empty string!!!");
20     local tree2 = TestBehaviorTree2:New();
21 
22     self:SetStartTask(repeater);
23 
24     repeater:AddChild(selector);
25 
26     selector:AddChild(sequence);
27     selector:AddChild(tree2);
28 
29     sequence:AddChild(isNullOrEmpty);
30     sequence:AddChild(log);
31 end

打印如下:

上面的执行结果是没有问题的,由此可见,将BTBehaviorTree当作节点,然后嵌套在行为树中是可行的。不过通过上面的打印,可以发现嵌套树先被打印,然后总树才被打印,而且嵌套树的层级也是不对的。

对于打印错误,这是节点添加顺序造成的问题,因此不应该在设置节点或者添加节点时进行打印,应该在整棵数构成完成后进行打印。

对于层级不对,可以在添加嵌套树后更新嵌套树下的节点层级。

Enum.lua

 1 --节点状态
 2 BTTaskStatus = {
 3     Inactive = 1,    --尚未执行
 4     Failure = 2,     --返回失败
 5     Success = 3,     --返回成功
 6     Running = 4,     --执行中
 7 }
 8 
 9 --节点类型
10 BTTaskType = {
11     Root = 0,
12     Action = 1,
13     Composite = 2,
14     Conditional = 3,
15     Decorator = 4,
16 }

BTBehaviorManager.lua

 1 BTBehaviorManager = {};
 2 
 3 local this = BTBehaviorManager;
 4 this.printTreeStr = "";
 5 
 6 function this.RunTree(tree)
 7     this.bTree = tree;
 8     this.OnUpdate();
 9 end
10 
11 function this.OnUpdate()
12     local status = this.bTree:OnUpdate();
13     while (status == BTTaskStatus.Running) do
14         status = this.bTree:OnUpdate();
15     end
16 end
17 
18 --深度优先,打印树结构
19 function this.PrintTree(task)
20     this.printTreeStr = "";
21     this.AddToPrintTreeStr(task);
22     print(this.printTreeStr);
23 end
24 
25 function this.AddToPrintTreeStr(task)
26     local taskType = task.taskType;
27     
28     this.printTreeStr = this.printTreeStr .. task:ToString() .. "
";
29 
30     if (taskType == BTTaskType.Root) then    
31         this.AddToPrintTreeStr(task.startTask);
32     elseif (taskType == BTTaskType.Composite or taskType == BTTaskType.Decorator) then
33         for i=1,#task.childTasks do
34             this.AddToPrintTreeStr(task.childTasks[i]);
35         end
36     else
37         
38     end
39 end

BTBehaviorTree.lua

 1 --[[
 2 树的根节点
 3 --]]
 4 BTBehaviorTree = BTTask:New();
 5 
 6 local this = BTBehaviorTree;
 7 this.taskType = BTTaskType.Root;
 8 
 9 function this:New()
10     local o = {};
11     setmetatable(o, self);
12     self.__index = self;
13     return o;
14 end
15 
16 --设置起始节点
17 function this:SetStartTask(task)
18     task.root = self;
19     task.parent = self;
20     task.layer = self.layer + 1;
21     self.startTask = task;
22 end
23 
24 --更新子节点层级
25 function this:UpdateLayer()
26     self:UpdateChildLayer(self.startTask);
27 end
28 
29 function this:UpdateChildLayer(task)
30     local taskType = task.taskType;
31     task.layer = task.root.layer + task.layer - 1;
32 
33     if (taskType == BTTaskType.Root) then    
34         self:UpdateChildLayer(task.startTask);
35     elseif (taskType == BTTaskType.Composite or taskType == BTTaskType.Decorator) then
36         for i=1,#task.childTasks do
37             self:UpdateChildLayer(task.childTasks[i]);
38         end
39     else
40         
41     end    
42 end
43 
44 function this:OnUpdate()
45     if (self.startTask) then
46         return self.startTask:OnUpdate();
47     end
48 end

打印如下:

原文地址:https://www.cnblogs.com/lyh916/p/9615606.html