• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

[Unity插件]Lua行为树(三):组合节点Sequence

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

Sequence的继承关系如下:

Sequence->Composite->ParentTask->Task

上一篇已经实现了简单版本的ParentTask和Task(基于Behavior Designer的源码),那么接下来看下Composite和Sequence。

1.Composite:表明该节点是组合节点,无特殊作用。

2.Sequence:

成员:

currentChildIndex:当前运行的子节点索引

executionStatus:当前运行的子节点状态

方法:

CanExecute:当有可运行的子节点并且子节点不返回失败时,返回true

OnChildExecuted:当一个子节点运行完后调用,将当前索引指向下一个节点,同时更新当前运行的子节点状态

OnEnd:Sequence运行结束时调用,重置变量

 1 namespace BehaviorDesigner.Runtime.Tasks
 2 {
 3     [TaskDescription("The sequence task is similar to an \"and\" operation. It will return failure as soon as one of its child tasks return failure. " +
 4                      "If a child task returns success then it will sequentially run the next task. If all child tasks return success then it will return success.")]
 5     [HelpURL("http://www.opsive.com/assets/BehaviorDesigner/documentation.php?id=25")]
 6     [TaskIcon("{SkinColor}SequenceIcon.png")]
 7     public class Sequence : Composite
 8     {
 9         // The index of the child that is currently running or is about to run.
10         private int currentChildIndex = 0;
11         // The task status of the last child ran.
12         private TaskStatus executionStatus = TaskStatus.Inactive;
13 
14         public override int CurrentChildIndex()
15         {
16             return currentChildIndex;
17         }
18 
19         public override bool CanExecute()
20         {
21             // We can continue to execuate as long as we have children that haven't been executed and no child has returned failure.
22             return currentChildIndex < children.Count && executionStatus != TaskStatus.Failure;
23         }
24 
25         public override void OnChildExecuted(TaskStatus childStatus)
26         {
27             // Increase the child index and update the execution status after a child has finished running.
28             currentChildIndex++;
29             executionStatus = childStatus;
30         }
31 
32         public override void OnConditionalAbort(int childIndex)
33         {
34             // Set the current child index to the index that caused the abort
35             currentChildIndex = childIndex;
36             executionStatus = TaskStatus.Inactive;
37         }
38 
39         public override void OnEnd()
40         {
41             // All of the children have run. Reset the variables back to their starting values.
42             executionStatus = TaskStatus.Inactive;
43             currentChildIndex = 0;
44         }
45     }
46 }

 

当然,因为Behavior Designer源码的代码量比较多,所以不可能完全地实现一个Lua版本的BD,不过可以参考里面的一些设计思想去实现一套行为树。

以Sequence节点为例:

1.如果当前节点返回Failure,则Sequence返回Failure,结束执行Sequence

2.如果当前节点返回Running,则Sequence返回Running,下一帧继续执行当前节点

3.如果当前节点返回Success,那么Sequence将会执行下一个节点,这里会出现两种做法,一是Sequence返回Running,等下一帧再执行下一节点;二是在同一帧下继续执行。这里我采用的是第二种,因为在早期的AI中,逻辑都是在Update中进行的,也就是逻辑都在同一帧中,因此我觉得放在同一帧中执行效率会高一些。

 

代码如下:

BTParentTask.lua

 1 BTParentTask = BTTask:New();
 2 
 3 local this = BTParentTask;
 4 
 5 function this:New()
 6     local o = {};
 7     setmetatable(o, self);
 8     self.__index = self;
 9     o.currentChildIndex = 0;  --当前运行到第几个子节点
10     o.currentChildTask = nil; --当前运行的子节点
11     o.childTasks = {};        --子节点列表
12     return o;
13 end
14 
15 function this:AddChild(task)
16     local index = #self.childTasks + 1;
17     task.index = index;
18     task.layer = self.layer + 1;
19     task.parent = self;
20     task.root = self.root;
21     self.childTasks[index] = task;
22 end
23 
24 --是否有子节点
25 function this:HasChild()
26     if (#self.childTasks > 0) then
27         return true;
28     else
29         return false;
30     end
31 end
32 
33 --获取下一个要执行的子节点
34 function this:GetNextChild()
35     if (#self.childTasks >= (self.currentChildIndex + 1)) then
36         self.currentChildIndex = self.currentChildIndex + 1;
37         return self.childTasks[self.currentChildIndex];
38     end
39     return nil;
40 end
41 
42 --重置
43 function this:Reset()
44     self.currentChildIndex = 0;
45     self.currentChildTask = nil;
46 end

 

BTSequence.lua

 1 BTSequence = BTComposite:New();
 2 
 3 local this = BTSequence;
 4 
 5 function this:New()
 6     local o = {};
 7     setmetatable(o, self);
 8     self.__index = self;
 9     o.executionStatus = BTTaskStatus.Inactive;
10     return o;
11 end
12 
13 function this:OnUpdate()
14     if (not self:HasChild()) then
15         return BTTaskStatus.Failure;
16     end
17 
18     if (not self.currentChildTask) then
19         self.currentChildTask = self:GetNextChild();
20         if (not self.currentChildTask) then
21             return BTTaskStatus.Failure;
22         end
23     end
24 
25     while (self.currentChildTask) do
26         self.executionStatus = self.currentChildTask:OnUpdate();
27         if (self.executionStatus == BTTaskStatus.Failure) then --结束
28             self:Reset();
29             return BTTaskStatus.Failure;
30         elseif (self.executionStatus == BTTaskStatus.Running) then --下一帧继续执行
31             return BTTaskStatus.Running;
32         else --继续执行下一节点
33             self.currentChildTask = self:GetNextChild();
34         end
35     end
36 
37     --所有节点执行完毕
38     self.executionStatus = BTTaskStatus.Success;
39     self:Reset();
40     return BTTaskStatus.Success;
41 end

 

TestBehaviorTree.lua

 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     local sequence = BTSequence:New();
15     local log = BTLog:New("hello world!");
16     local log2 = BTLog:New("This is a test");
17     sequence:AddChild(log);
18     sequence:AddChild(log2);
19     this:PushTask(sequence);
20 end

 

打印如下:


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Lua笔记发布时间:2022-07-22
下一篇:
lua知识点整理发布时间:2022-07-22
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap