[Unity插件]Lua行为树(十二):行为树管理

之前运行的行为树,都是一颗总树,那么实际上会有很多的总树,因此需要对行为树进行管理。

BTBehaviorManager.lua

 1 BTBehaviorManager = {};
 2 
 3 local this = BTBehaviorManager;
 4 this.isEachFrameCall = false;--是否是每帧调用
 5 this.printTreeStr = "";
 6 this.trees = {};
 7 
 8 function this.RunTree()
 9     if (isEachFrameCall) then
10     else
11         while (true) do
12             local isAllFinish = this.OnUpdate();
13             if (isAllFinish) then
14                 break;
15             end
16         end
17     end
18 end
19 
20 function this.OnUpdate()
21     local count = 0;
22 
23     for i=1,#this.trees do
24         local tree = this.trees[i];
25         if (tree.executionStatus == BTTaskStatus.Inactive) then --第一次执行
26             print("第一次执行:" .. tree.name);
27             tree:OnUpdate();
28         elseif (tree.executionStatus == BTTaskStatus.Running) then --第二次以及以后执行
29             print("第二次以及以后执行:" .. tree.name);
30             tree:OnUpdate();
31         else
32             count = count + 1;
33         end
34     end
35 
36     if (count == #this.trees) then
37         return true;
38     else
39         return false;         
40     end
41 end
42 
43 --添加行为树
44 function this.AddTree(task)
45     table.insert(this.trees, task);
46 end
47 
48 --深度优先,打印树结构
49 function this.PrintTree(task)
50     this.printTreeStr = "";
51     this.AddToPrintTreeStr(task);
52     print(this.printTreeStr);
53 end
54 
55 function this.AddToPrintTreeStr(task)
56     local taskType = task.taskType;
57     
58     this.printTreeStr = this.printTreeStr .. task:ToString() .. "\n";
59 
60     if (taskType == BTTaskType.Root) then    
61         this.AddToPrintTreeStr(task.startTask);
62     elseif (taskType == BTTaskType.Composite or taskType == BTTaskType.Decorator) then
63         for i=1,#task.childTasks do
64             this.AddToPrintTreeStr(task.childTasks[i]);
65         end
66     else
67         
68     end
69 end

说明:

1.因为是运行在Sublime环境下的,所以这里使用while循环模拟每帧调用

2.关于AddTree和OnUpdate是否会冲突的问题。AddTree会增加trees的长度,但是在lua中for的三个表达式在循环开始前一次性求值,以后不再进行求值。比如#this.trees这个表达式只会在循环开始前执行一次,其结果用在后面的循环中。也就是说,如果在for循环过程中执行了AddTree方法,新增的元素会添加在后面,不会影响for循环的。

测试:

多行为树执行

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     o:Init();
11     return o;
12 end
13 
14 function this:Init()
15     local parallel = BTParallel:New();
16     local action = self:GetBTActionUniversal();
17     local action2 = self:GetBTActionUniversal2();
18 
19     self:SetStartTask(parallel);
20 
21     parallel:AddChild(action);
22     parallel:AddChild(action2);
23 end
24 
25 function this:GetBTActionUniversal()
26     local count = 1;
27     local a = function ()
28         if (count <= 3) then
29             count = count + 1;
30             print("22");
31             return BTTaskStatus.Running;
32         else
33             return BTTaskStatus.Success;
34         end
35     end
36     local universal = BTActionUniversal:New(nil, a);
37     return universal;
38 end
39 
40 function this:GetBTActionUniversal2()
41     local universal = BTActionUniversal:New(nil, function ()
42         return BTTaskStatus.Success;
43     end);
44     return universal;
45 end

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     o: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

TestMain.lua

 1 require "BehaviorTree/Core/Init"
 2 require "BehaviorTree/Test/TestBehaviorTree"
 3 require "BehaviorTree/Test/TestBehaviorTree2"
 4 
 5 local tree = TestBehaviorTree:New();
 6 local tree2 = TestBehaviorTree2:New();
 7 tree.name = "tree";
 8 tree2.name = "tree2";
 9 BTBehaviorManager.AddTree(tree);
10 BTBehaviorManager.AddTree(tree2);
11 BTBehaviorManager.RunTree();

输出如下:

猜你喜欢

转载自www.cnblogs.com/lyh916/p/9689607.html
今日推荐