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
第一个输出:
第二个输出(循环执行):
第三个输出:
第四个输出: