zoukankan      html  css  js  c++  java
  • [Unity插件]Lua行为树(五):装饰节点Repeater

    Repeater:重复执行子节点,直到一定次数

    特点如下:

    1.执行次数可以是无限循环,也可以是固定次数

    2.一般来说,子节点的执行返回状态不会影响Repeater节点,但可以设置当子节点返回失败时,结束执行Repeater节点

    Repeater的继承关系如下:

    Repeater->Decorator->ParentTask->Task

    因为继承装饰节点,所以其子节点只能有一个

    Repeater.cs

     1 namespace BehaviorDesigner.Runtime.Tasks
     2 {
     3     [TaskDescription(@"The repeater task will repeat execution of its child task until the child task has been run a specified number of times. " +
     4                       "It has the option of continuing to execute the child task even if the child task returns a failure.")]
     5     [HelpURL("http://www.opsive.com/assets/BehaviorDesigner/documentation.php?id=37")]
     6     [TaskIcon("{SkinColor}RepeaterIcon.png")]
     7     public class Repeater : Decorator
     8     {
     9         [Tooltip("The number of times to repeat the execution of its child task")]
    10         public SharedInt count = 1;
    11         [Tooltip("Allows the repeater to repeat forever")]
    12         public SharedBool repeatForever;
    13         [Tooltip("Should the task return if the child task returns a failure")]
    14         public SharedBool endOnFailure;
    15 
    16         // The number of times the child task has been run.
    17         private int executionCount = 0;
    18         // The status of the child after it has finished running.
    19         private TaskStatus executionStatus = TaskStatus.Inactive;
    20 
    21         public override bool CanExecute()
    22         {
    23             // Continue executing until we've reached the count or the child task returned failure and we should stop on a failure.
    24             return (repeatForever.Value || executionCount < count.Value) && (!endOnFailure.Value || (endOnFailure.Value && executionStatus != TaskStatus.Failure));
    25         }
    26 
    27         public override void OnChildExecuted(TaskStatus childStatus)
    28         {
    29             // The child task has finished execution. Increase the execution count and update the execution status.
    30             executionCount++;
    31             executionStatus = childStatus;
    32         }
    33 
    34         public override void OnEnd()
    35         {
    36             // Reset the variables back to their starting values.
    37             executionCount = 0;
    38             executionStatus = TaskStatus.Inactive;
    39         }
    40 
    41         public override void OnReset()
    42         {
    43             // Reset the public properties back to their original values.
    44             count = 0;
    45             endOnFailure = true;
    46         }
    47     }
    48 }

    BTDecorator.lua

     1 BTDecorator = BTParentTask:New();
     2 
     3 local this = BTDecorator;
     4 
     5 function this:New()
     6     local o = {};
     7     setmetatable(o, self);
     8     self.__index = self;
     9     return o;
    10 end
    11 
    12 function this:GetChild()
    13     if (self:GetChildCount() ~= 1) then
    14         return nil;
    15     end
    16     return self.childTasks[1];
    17 end

    BTRepeater.lua

     1 BTRepeater = BTDecorator:New();
     2 
     3 local this = BTRepeater;
     4 
     5 function this:New(count, endOnFailure)
     6     local o = {};
     7     setmetatable(o, self);
     8     self.__index = self;
     9     o.executionStatus = BTTaskStatus.Inactive;
    10     o.count = count or -1;                       --执行次数,-1为循环执行
    11     o.endOnFailure = endOnFailure or false;      --子节点返回Failure时,是否结束
    12     o.executionCount = 0;                        --当前执行次数
    13     return o;
    14 end
    15 
    16 function this:OnUpdate()
    17     if (not self.currentChildTask) then
    18         self.currentChildTask = self:GetChild();
    19         if (not self.currentChildTask) then
    20             return BTTaskStatus.Failure;
    21         end
    22     end
    23 
    24     local canExecute = false;
    25     if (((self.count == -1) or (self.executionCount < self.count)) and
    26         ((not self.endOnFailure) or (self.endOnFailure and self.executionStatus ~= BTTaskStatus.Failure))) then
    27         canExecute = true;
    28     end
    29 
    30     if (canExecute) then
    31         self.executionStatus = self.currentChildTask:OnUpdate();
    32         self.executionCount = self.executionCount + 1;
    33     end
    34 
    35     if (self.endOnFailure and self.executionStatus == BTTaskStatus.Failure) then
    36         self:Reset();
    37         return BTTaskStatus.Success;
    38     elseif (self.executionCount == self.count) then
    39         self:Reset();
    40         return BTTaskStatus.Success;
    41     else
    42         return BTTaskStatus.Running;
    43     end
    44 end
    45 
    46 function this:Reset()
    47     self.executionStatus = BTTaskStatus.Inactive;
    48     self.executionCount = 0;
    49     BTParentTask.Reset(self);
    50 end

    测试:

     1 TestBehaviorTree = BTBehaviorTree:New();
     2 
     3 local this = TestBehaviorTree;
     4 
     5 function this:New()
     6     local o = {};
     7     setmetatable(o, self);
     8     self.__index = self;
     9     this:Init();
    10     return o;
    11 end
    12 
    13 function this:Init()
    14     --1.一定的执行次数
    15     local repeater = BTRepeater:New(5);
    16     local log = BTLog:New("This is a BTRepeater test");
    17     repeater:AddChild(log);
    18 
    19     --2.循环执行
    20     --[[local repeater = BTRepeater:New();
    21     local log = BTLog:New("This is a BTRepeater test");
    22     repeater:AddChild(log);--]]
    23 
    24     --3.endOnFailure false
    25     --[[local repeater = BTRepeater:New(3);
    26     local sequence = BTSequence:New();
    27     local log = BTLog:New("First Child");
    28     local isNullOrEmpty = BTIsNullOrEmpty:New("123");
    29     local log2 = BTLog:New("This is a empty string");
    30     sequence:AddChild(log);
    31     sequence:AddChild(isNullOrEmpty);
    32     sequence:AddChild(log2);
    33     repeater:AddChild(sequence);--]]
    34 
    35     --4.endOnFailure true
    36     --[[local repeater = BTRepeater:New(3, true);
    37     local sequence = BTSequence:New();
    38     local log = BTLog:New("First Child");
    39     local isNullOrEmpty = BTIsNullOrEmpty:New("123");
    40     local log2 = BTLog:New("This is a empty string");
    41     sequence:AddChild(log);
    42     sequence:AddChild(isNullOrEmpty);
    43     sequence:AddChild(log2);
    44     repeater:AddChild(sequence);--]]
    45 
    46     this:PushTask(repeater);
    47 end

    第一个输出:

    第二个输出(循环执行):

    第三个输出:

    第四个输出:

  • 相关阅读:
    解决mac osx下pip安装ipython权限的问题
    [转载][翻译]Go的50坑:新Golang开发者要注意的陷阱、技巧和常见错误[1]
    PhantomJS 基础及示例 (转)
    Go -- 别人的博客
    [转]Go的50坑:新Golang开发者要注意的陷阱、技巧和常见错误-高级
    Go -- etcd详解(转)
    对require.js 的使用进行总结
    gatsbyjs 使用
    gatsbyjs 了解
    JAMstack 最佳实践
  • 原文地址:https://www.cnblogs.com/lyh916/p/9576478.html
Copyright © 2011-2022 走看看