• [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() .. "
    ";
    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循环的。

    测试:

    1.多行为树执行

    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();

    输出如下:

    2.for循环中添加行为树

    TestBehaviorTree3.lua

     1 TestBehaviorTree3 = BTBehaviorTree:New();
     2 
     3 local this = TestBehaviorTree3;
     4 this.name = "TestBehaviorTree3";
     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 log = BTLog:New("This is TestBehaviorTree3 tree!!!");
    17 
    18     self:SetStartTask(repeater);
    19 
    20     repeater:AddChild(log);
    21 end

    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 local temp = false;
    21 
    22 function this.OnUpdate()
    23     local count = 0;
    24 
    25     for i=1,#this.trees do
    26         if (not temp) then
    27             temp = true;
    28             require "BehaviorTree/Test/TestBehaviorTree3"
    29             local tree3 = TestBehaviorTree3:New();
    30             tree3.name = "tree3";
    31             this.AddTree(tree3);
    32         end
    33 
    34         local tree = this.trees[i];
    35         if (tree.executionStatus == BTTaskStatus.Inactive) then --第一次执行
    36             print("第一次执行:" .. tree.name);
    37             tree:OnUpdate();
    38         elseif (tree.executionStatus == BTTaskStatus.Running) then --第二次以及以后执行
    39             print("第二次以及以后执行:" .. tree.name);
    40             tree:OnUpdate();
    41         else
    42             count = count + 1;
    43         end
    44     end
    45 
    46     print("------------------------------");
    47 
    48     if (count == #this.trees) then
    49         return true;
    50     else
    51         return false;         
    52     end
    53 end
    54 
    55 --添加行为树
    56 function this.AddTree(task)
    57     table.insert(this.trees, task);
    58 end
    59 
    60 --深度优先,打印树结构
    61 function this.PrintTree(task)
    62     this.printTreeStr = "";
    63     this.AddToPrintTreeStr(task);
    64     print(this.printTreeStr);
    65 end
    66 
    67 function this.AddToPrintTreeStr(task)
    68     local taskType = task.taskType;
    69     
    70     this.printTreeStr = this.printTreeStr .. task:ToString() .. "
    ";
    71 
    72     if (taskType == BTTaskType.Root) then    
    73         this.AddToPrintTreeStr(task.startTask);
    74     elseif (taskType == BTTaskType.Composite or taskType == BTTaskType.Decorator) then
    75         for i=1,#task.childTasks do
    76             this.AddToPrintTreeStr(task.childTasks[i]);
    77         end
    78     else
    79         
    80     end
    81 end

    输出如下。可以看到,在第一帧时,添加了行为树tree3,但是并不影响tree和tree2的执行,而在第二帧以及以后的帧时,tree3也开始执行了。

  • 相关阅读:
    python 中给文件加锁——fcntl模块
    python生成二维码
    uwsgi常用配置
    php curl实现get和post请求
    python __enter__ 与 __exit__的作用,以及与 with 语句的关系
    python文件操作总结
    Python时间,日期,时间戳之间转换
    Python random模块(获取随机数)
    wigs的理解和应用
    shiro中接入单点登录功能
  • 原文地址:https://www.cnblogs.com/lyh916/p/9689607.html
Copyright © 2020-2023  润新知