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 end11 12 function this:GetChild()13 if (self:GetChildCount() ~= 1) then14 return nil;15 end16 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 end15 16 function this:OnUpdate()17 if (not self.currentChildTask) then18 self.currentChildTask = self:GetChild();19 if (not self.currentChildTask) then20 return BTTaskStatus.Failure;21 end22 end23 24 local canExecute = false;25 if (((self.count == -1) or (self.executionCount < self.count)) and26 ((not self.endOnFailure) or (self.endOnFailure and self.executionStatus ~= BTTaskStatus.Failure))) then27 canExecute = true;28 end29 30 if (canExecute) then31 self.executionStatus = self.currentChildTask:OnUpdate();32 self.executionCount = self.executionCount + 1;33 end34 35 if (self.endOnFailure and self.executionStatus == BTTaskStatus.Failure) then36 self:Reset();37 return BTTaskStatus.Success;38 elseif (self.executionCount == self.count) then39 self:Reset();40 return BTTaskStatus.Success;41 else42 return BTTaskStatus.Running;43 end44 end45 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 end12 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 false25 --[[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 true36 --[[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
第一个输出:
第二个输出(循环执行):
第三个输出:
第四个输出:
posted on 2018-09-02 23:55 阅读( ...) 评论( ...) 收藏