lyh916

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

Parallel节点类似Sequence节点,不同在于Parallel会每帧执行所有的节点。当所有节点返回成功时返回成功,当其中一个节点返回失败时,返回失败并且结束所有的子节点运行。

例如说,给Sequence节点插入一个不断返回Running的行为节点,那么就会造成后面的子节点无法执行,而对于Parallel来说,是不会存在这种阻塞情况的。

 

Parallel.cs

 1 namespace BehaviorDesigner.Runtime.Tasks
 2 {
 3     [TaskDescription("Similar to the sequence task, the parallel task will run each child task until a child task returns failure. " +
 4                      "The difference is that the parallel task will run all of its children tasks simultaneously versus running each task one at a time. " +
 5                      "Like the sequence class, the parallel task will return success once all of its children tasks have return success. " +
 6                      "If one tasks returns failure the parallel task will end all of the child tasks and return failure.")]
 7     [HelpURL("http://www.opsive.com/assets/BehaviorDesigner/documentation.php?id=27")]
 8     [TaskIcon("{SkinColor}ParallelIcon.png")]
 9     public class Parallel : Composite
10     {
11         // The index of the child that is currently running or is about to run.
12         private int currentChildIndex;
13         // The task status of every child task.
14         private TaskStatus[] executionStatus;
15 
16         public override void OnAwake()
17         {
18             // Create a new task status array that will hold the execution status of all of the children tasks.
19             executionStatus = new TaskStatus[children.Count];
20         }
21 
22         public override void OnChildStarted(int childIndex)
23         {
24             // One of the children has started to run. Increment the child index and set the current task status of that child to running.
25             currentChildIndex++;
26             executionStatus[childIndex] = TaskStatus.Running;
27         }
28 
29         public override bool CanRunParallelChildren()
30         {
31             // This task can run parallel children.
32             return true;
33         }
34 
35         public override int CurrentChildIndex()
36         {
37             return currentChildIndex;
38         }
39 
40         public override bool CanExecute()
41         {
42             // We can continue executing if we have more children that haven't been started yet.
43             return currentChildIndex < children.Count;
44         }
45 
46         public override void OnChildExecuted(int childIndex, TaskStatus childStatus)
47         {
48             // One of the children has finished running. Set the task status.
49             executionStatus[childIndex] = childStatus;
50         }
51 
52         public override TaskStatus OverrideStatus(TaskStatus status)
53         {
54             // Assume all of the children have finished executing. Loop through the execution status of every child and check to see if any tasks are currently running
55             // or failed. If a task is still running then all of the children are not done executing and the parallel task should continue to return a task status of running.
56             // If a task failed then return failure. The Behavior Manager will stop all of the children tasks. If no child task is running or has failed then the parallel
57             // task succeeded and it will return success.
58             bool childrenComplete = true;
59             for (int i = 0; i < executionStatus.Length; ++i) {
60                 if (executionStatus[i] == TaskStatus.Running) {
61                     childrenComplete = false;
62                 } else if (executionStatus[i] == TaskStatus.Failure) {
63                     return TaskStatus.Failure;
64                 }
65             }
66             return (childrenComplete ? TaskStatus.Success : TaskStatus.Running);
67         }
68 
69         public override void OnConditionalAbort(int childIndex)
70         {
71             // Start from the beginning on an abort
72             currentChildIndex = 0;
73             for (int i = 0; i < executionStatus.Length; ++i) {
74                 executionStatus[i] = TaskStatus.Inactive;
75             }
76         }
77 
78         public override void OnEnd()
79         {
80             // Reset the execution status and the child index back to their starting values.
81             for (int i = 0; i < executionStatus.Length; ++i) {
82                 executionStatus[i] = TaskStatus.Inactive;
83             }
84             currentChildIndex = 0;
85         }
86     }
87 }

 

BTParallel.lua

 1 BTParallel = BTComposite:New();
 2 
 3 local this = BTParallel;
 4 this.name = "BTParallel";
 5 
 6 function this:New()
 7     local o = {};
 8     setmetatable(o, self);
 9     self.__index = self;
10     o.childTasks = {};
11     o.executionStatus = {};
12     return o;
13 end
14 
15 function this:OnUpdate()
16     if (not self:HasChild()) then
17         return BTTaskStatus.Failure;
18     end
19 
20     for i=1,#self.childTasks do
21         local childTask = self.childTasks[i];
22         if (not self.executionStatus[i]) then --第一次执行
23             self.executionStatus[i] = childTask:OnUpdate();
24             if (self.executionStatus[i] == BTTaskStatus.Failure) then
25                 return BTTaskStatus.Failure;
26             end
27         elseif (self.executionStatus[i] == BTTaskStatus.Running) then --第二次以及以后执行
28             self.executionStatus[i] = childTask:OnUpdate();
29             if (self.executionStatus[i] == BTTaskStatus.Failure) then
30                 return BTTaskStatus.Failure;
31             end
32         end
33     end
34 
35     local childrenComplete = true;
36     for i=1,#self.executionStatus do
37         if (self.executionStatus[i] == BTTaskStatus.Running) then
38             childrenComplete = false;
39             break;
40         end
41     end
42     if (childrenComplete) then
43         return BTTaskStatus.Success;
44     else
45         return BTTaskStatus.Running;
46     end
47 end

 

测试如下:

1.BTSequence和BTParallel的对比

 BTSequence:

 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     o:Init();
11     return o;
12 end
13 
14 function this:Init()
15     local sequence = BTSequence:New();
16     local action = self:GetBTActionUniversal();
17     local log = BTLog:New("This is log!!!");
18     log.name = "log";
19 
20     self:SetStartTask(sequence);
21 
22     sequence:AddChild(action);
23     sequence:AddChild(log);
24 end
25 
26 function this:GetBTActionUniversal()
27     local count = 1;
28     local a = function ()
29         if (count <= 3) then
30             count = count + 1;
31             print("22");
32             return BTTaskStatus.Running;
33         else
34             return BTTaskStatus.Success;
35         end
36     end
37     local universal = BTActionUniversal:New(nil, a);
38     return universal;
39 end

 

BTParallel:

 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     o:Init();
11     return o;
12 end
13 
14 function this:Init()
15     local parallel = BTParallel:New();
16     local action = self:GetBTActionUniversal();
17     local log = BTLog:New("This is log!!!");
18     log.name = "log";
19 
20     self:SetStartTask(parallel);
21 
22     parallel:AddChild(action);
23     parallel:AddChild(log);
24 end
25 
26 function this:GetBTActionUniversal()
27     local count = 1;
28     local a = function ()
29         if (count <= 3) then
30             count = count + 1;
31             print("22");
32             return BTTaskStatus.Running;
33         else
34             return BTTaskStatus.Success;
35         end
36     end
37     local universal = BTActionUniversal:New(nil, a);
38     return universal;
39 end

 

2.BTParallel中返回失败中断执行的情况

 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     o:Init();
11     return o;
12 end
13 
14 function this:Init()
15     local parallel = BTParallel:New();
16     local action = self:GetBTActionUniversal();
17     local action2 = self:GetBTActionUniversal2();
18 
19     self:SetStartTask(parallel);
20 
21     parallel:AddChild(action);
22     parallel:AddChild(action2);
23 end
24 
25 function this:GetBTActionUniversal()
26     local count = 1;
27     local a = function ()
28         if (count <= 3) then
29             count = count + 1;
30             print("22");
31             return BTTaskStatus.Running;
32         else
33             return BTTaskStatus.Success;
34         end
35     end
36     local universal = BTActionUniversal:New(nil, a);
37     return universal;
38 end
39 
40 function this:GetBTActionUniversal2()
41     local universal = BTActionUniversal:New(nil, function ()
42         return BTTaskStatus.Failure;
43     end);
44     return universal;
45 end

posted on 2018-09-18 00:03  艰苦奋斗中  阅读(1676)  评论(0编辑  收藏  举报