lyh916

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

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

 

第一个输出:

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

第三个输出:

第四个输出:

posted on 2018-09-02 23:55  艰苦奋斗中  阅读(1120)  评论(0编辑  收藏  举报