zoukankan      html  css  js  c++  java
  • [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

    打印如下:

  • 相关阅读:
    SQL Server 2008 R2——VC++ ADO 操作 多线程操作 代码结构
    SQL Server 2008 R2——VC++ ADO 操作 参数化查询
    SQL Server 2008 R2——VC++ ADO 操作 事务
    SQL Server 2008 R2——VC++ ADO 操作 存储过程
    SQL Server 2008 R2——开发资料搜集
    SQL Server 2008 R2——学习/练习/错误/总结/搜集
    CListCtrl中删除多个不连续的行
    C++基础——子类转父类转子类 (派生类转基类转派生类)
    魔改——MDI多视图模板Tab/标签页 初始化/操作控件
    魔改——MFC SDI程序 转换为 MDI程序
  • 原文地址:https://www.cnblogs.com/lyh916/p/9615606.html
Copyright © 2011-2022 走看看