123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417 |
- ---
- --- Generated by EmmyLua(https://github.com/EmmyLua)
- --- Created by xxn.
- --- DateTime: 2021/1/7 13:25
- ---
- -- 行为树各类节点
- --[[
- 行为树节点主要分为:
- 1、组合节点(序列节点、选择节点、并行节点等)
- 2、装饰节点(且只能有一个子节点)
- 3、条件节点
- 4、动作节点
- 只有条件节点和动作节点能做完行为树的叶子节点,
- 而组合、装饰节点控制行为树的决策走向,所以,
- 条件和动作节点称为行为节点(Behavior Node),
- 组合和装饰节点称为决策节点(Decider Node)。
- 只有叶子节点才需要特别定制。
- --]]
- -- 行为树节点父类
- ---@class BehaviorNode
- BehaviorNode = class()
- ---@param children BehaviorNode[]
- function BehaviorNode:ctor(children)
- self.parent = nil
- self.kind = BehaviorNodeEnum.BehaviourNode --行为树节点种类
- self.children = children --子节点列表(数组)
- self.owner = nil --行为树拥有者
- self.status = BehaviorStatusEnum.READY --当前状态
- self.lastResult = BehaviorStatusEnum.READY --上一次结果
-
- if children then
- for _,child in ipairs(children) do
- child.parent = self
- end
- end
- end
- function BehaviorNode:SetOwner(owner)
- self.owner = owner
- if self.children then
- for k, child in ipairs(self.children) do
- child:SetOwner(owner)
- end
- end
- end
- function BehaviorNode:IsKindOf(k)
- return self.kind == k
- end
- function BehaviorNode:Visit()
-
- end
- -- 步进
- -- 如果该处于运行中并且有子节点,则步进子节点; 否则,重置该节点以及子节点
- function BehaviorNode:Step()
- if self.status ~= BehaviorStatusEnum.RUNNING then
- self:Reset()
- elseif self.children then
- for k, v in ipairs(self.children) do
- v:Step()
- end
- end
- end
- -- 重置节点为ready状态
- function BehaviorNode:Reset()
- if self.status ~= BehaviorStatusEnum.READY then
- self.status = BehaviorStatusEnum.READY
- if self.children then
- for _, child in ipairs(self.children) do
- child:Reset()
- end
- end
- end
- end
- function BehaviorNode:Stop()
- if self.children then
- for _, child in ipairs(self.children) do
- child:Stop()
- end
- end
- end
- -- 保存上一次update的状态
- function BehaviorNode:SaveStatus()
- self.lastResult = self.status
- if self.children then
- for k,v in ipairs(self.children) do
- v:SaveStatus()
- end
- end
- end
- ---@param nodeEnum BehaviorNodeEnum
- function BehaviorNode:FindNode(nodeEnum)
- if self.kind == nodeEnum then
- return self
- end
- if self.children then
- for k, v in pairs(self.children) do
- local f = v:FindNode(v)
- if f then
- return f
- end
- end
- end
- end
- ------------------------------------- 条件节点 -------------------------------------
- --[[
- 条件节点根据比较结果返回成功或失败,但永远不会返回正在执行(Running)
- --]]
- ---@class ConditionNode:BehaviorNode
- ConditionNode = class(BehaviorNode)
- function ConditionNode:ctor(func)
- BehaviorNode.ctor(self)
- self.kind = BehaviorNodeEnum.ConditionNode
- self.func = func
- end
- -- 条件为true则返回成功
- function ConditionNode:Visit()
- if self.func and self.func() then
- self.status = BehaviorStatusEnum.SUCCESS
- else
- self.status = BehaviorStatusEnum.FAILED
- end
- end
- ------------------------------------- 动作节点 -------------------------------------
- -- 通常对应owner的某个方法,一般是个瞬间动作,比如放个技能
- ---@class ActionNode:BehaviorNode
- ActionNode = class(BehaviorNode)
- function ActionNode:ctor(action, resetFnc)
- BehaviorNode.ctor(self)
- self.kind = BehaviorNodeEnum.ActionNode
- self.action = action
- self.resetFnc = resetFnc
- end
- function ActionNode:Reset()
- BehaviorNode.Reset(self)
- if self.resetFnc then
- self.resetFnc()
- end
- end
- function ActionNode:Visit()
- if self.action then
- self.action()
- end
- self.status = BehaviorStatusEnum.SUCCESS
- end
- ------------------------------------- 组合节点 -------------------------------------
- -- 序列节点
- --[[
- 它实现的是and的逻辑,例如:r = x and y and z,则先执行x,如果x为true,则继续执行y,如果x为false,则直接返回false,以此类推
- 执行该节点时,它会一个接一个运行,
- 如果子节点状态为success,则执行下一个子节点;
- 如果子节点状态为running,则把自身设置为running,并等待返回其他结果(success或failed);
- 如果子节点状态为failed,则把自身设置为failed,并返回;
- 如果所有节点都为success,则把自身设置为success并返回。
- 原则:只要一个子节点返回"失败"或"运行中",则返回;若返回"成功",则执行下一个子节点。
- --]]
- ---@class SequenceNode:BehaviorNode
- SequenceNode = class(BehaviorNode)
- function SequenceNode:ctor(children)
- BehaviorNode.ctor(self, children)
- self.kind = BehaviorNodeEnum.SequenceNode
- self.index = 1 -- 运行的是第几个节点
- end
- function SequenceNode:Reset()
- self.index = 1
- BehaviorNode.Reset(self)
- end
- function SequenceNode:Visit()
- if self.status ~= BehaviorStatusEnum.RUNNING then --如果没有运行的子节点,则从头开始执行
- self.index = 1
- end
- local count = #self.children
- local child
- local status
- while self.index <= count do
- child = self.children[self.index]
- child:Visit()
- status = child.status
- if status == BehaviorStatusEnum.RUNNING or status == BehaviorStatusEnum.FAILED then
- self.status = status
- if BTMgr.IsDebug == true then
- if child.nodeName == nil then
- -- 这些是中间节点,非叶子节点
- else
- logError(child.nodeName .. ' ' .. child.status)
- end
- end
-
- return
- end
- self.index = self.index + 1
- end
- self.status = BehaviorStatusEnum.SUCCESS --所有子节点都返回success
- end
- -- 选择节点
- --[[
- 它实现的是or的逻辑,例如:r = x or y or z,则先执行x,如果x为false,则继续执行y,如果x为true,则直接返回true,以此类推
- 执行该节点时,它会一个接一个运行,
- 如果子节点状态为success,则把自身设置为success并返回;
- 如果子节点状态为running,则把自身设置为running,并等待返回其他结果(success或failed);
- 如果子节点状态为failed,则会执行下一个子节点;
- 如果所有没子节点都不为success,则把自身设置为failed并返回。
- 原则:只要一个子节点返回"成功"或"运行中",则返回;若返回"失败",则执行下一个子节点。
- --]]
- ---@class SelectorNode:BehaviorNode
- SelectorNode = class(BehaviorNode)
- function SelectorNode:ctor(children)
- BehaviorNode.ctor(self, children)
- self.kind = BehaviorNodeEnum.SelectorNode
- self.index = 1 -- 运行的是第几个节点
- end
- function SelectorNode:Reset()
- self.index = 1
- BehaviorNode.Reset(self)
- end
- function SelectorNode:Visit()
- if self.status ~= BehaviorStatusEnum.RUNNING then --如果没有运行的子节点,则从头开始执行
- self.index = 1
- end
- local count = #self.children
- local child
- local status
- while self.index <= count do
- child = self.children[self.index]
- child:Visit()
- status = child.status
- if status == BehaviorStatusEnum.SUCCESS or status == BehaviorStatusEnum.RUNNING then
- self.status = status
- if BTMgr.IsDebug == true then
- if child.nodeName == nil then
- -- 这些是中间节点,非叶子节点
- else
- logError(child.nodeName .. ' ' .. child.status)
- end
- end
- return
- end
- self.index = self.index + 1
- end
- self.status = BehaviorStatusEnum.FAILED --所有子节点都返回failed
- end
- -- 并行节点
- --[[
- 看上去是同时执行所有的子节点,但是真正的逻辑还是一个一个执行子节点。
- 它实现的是and的逻辑,例如:r = x and y and z,则先执行x,如果x为true或者runing,则继续执行y,如果x为false,则直接返回false,以此类推
- 如果子节点的状态是failed,则将自身设置为failed,并返回;
- 如果子节点是success或者running,则运行下一个子节点;
- 如果所有子节点都为success,则将自身设置为success并返回,否则设置自身为running。
- 在运行到该节点时,要对部分节点(ConditionNode、NotDecorator)做重置,重启判断。
- ps:这里的实现的其实是Parallel Sequence Node,如果子节点failed,则返回。
- 并行节点可以设置退出条件
- 和序列节点不同的是,序列节点子节点返回runing状态的时候就返回不执行后面的节点
- 并行节点是返回runing状态的时候就返回继续执行后面的节点
- 他们遇到子节点false时都返回,不执行后面的节点
- --]]
- ---@class ParallelNode:BehaviorNode
- ParallelNode = class(BehaviorNode)
- function ParallelNode:ctor(children)
- BehaviorNode.ctor(self, children)
- self.kind = BehaviorNodeEnum.ParallelNode
- self.stopOnAnyComplete = nil
- end
- function ParallelNode:Step()
- if self.status ~= BehaviorStatusEnum.RUNNING then
- self:Reset()
- else
- --只重置条件子节点
- if self.children then
- for i,child in ipairs(self.children) do
- if self:IsKindOf(BehaviorNodeEnum.ConditionNode)
- and child.status == BehaviorStatusEnum.SUCCESS then
- child:Reset()
- end
- end
- end
- end
- end
- function ParallelNode:Visit()
- local done = true --是否所有子节点都success
- local any_done = false
- for _, child in ipairs(self.children) do
- if child:IsKindOf(BehaviorNodeEnum.ConditionNode) then --重启条件节点
- child:Reset()
- end
- if child.status ~= BehaviorStatusEnum.SUCCESS then
- child:Visit()
- if child.status == BehaviorStatusEnum.FAILED then
- self.status = BehaviorStatusEnum.FAILED
- return
- end
- end
- if child.status == BehaviorStatusEnum.RUNNING then
- done = false
- else -- success
- any_done = true
- end
- end
- if done or (self.stopOnAnyComplete and any_done) then
- self.status = BehaviorStatusEnum.SUCCESS
- else
- self.status = BehaviorStatusEnum.RUNNING
- end
- end
- --if 节点
- --实现了if操作,只有cond为success时,node才会被执行
- --注意:如果node处于运行中,则会在下一次思考时,继续执行node节点,直到node返回成功或失败,该节点才会退出
- --如果node节点有可能出现运行中状态,则该节点不适用
- ---@class IfNode:BehaviorNode
- IfNode = class(SequenceNode)
- function IfNode:ctor(condFunc, node)
- local children = {ConditionNode(condFunc),node}
- SequenceNode.ctor(self, children)
- self.kind = BehaviorNodeEnum.IfNode
- end
- ---status值由node或者elseNode决定,node和elseNode可以再套IfElseNode
- ---@class IfElseNode:BehaviorNode
- IfElseNode = class(BehaviorNode)
- ---@param node BehaviorNode
- ---@param elseNode BehaviorNode
- function IfElseNode:ctor(condFunc, node,elseNode)
- local children = {node,elseNode}
- BehaviorNode.ctor(self, children)
- self.kind = BehaviorNodeEnum.IfElseNode
- self.condFunc = condFunc
- self.node = node
- self.elseNode = elseNode
- self.runingNode = nil
- end
- function IfElseNode:Visit()
- if self.lastVisitNode then
- self.lastVisitNode:Visit()
- self.status = self.lastVisitNode.status
- if self.status ~= BehaviorStatusEnum.RUNNING then
- self.lastVisitNode = nil
- end
- return
- end
- if self.condFunc() then
- self.node:Visit()
- self.lastVisitNode = self.node
- self.status = self.node.status
- else
- self.elseNode:Visit()
- self.lastVisitNode = self.elseNode
- self.status = self.elseNode.status
- end
- if self.status ~= BehaviorStatusEnum.RUNNING then
- self.lastVisitNode = nil
- end
- end
- --- wait 节点
- --等待条件达成继续运行
- ---@class WaitNode : BehaviorNode
- WaitNode = class(BehaviorNode)
- ---@param waitFun function @等待判定方法
- function WaitNode:ctor(waitFun)
- BehaviorNode.ctor(self, nil)
- self.waitFun = waitFun
- end
- function WaitNode:Reset()
- BehaviorNode.Reset(self)
- end
- function WaitNode:Visit()
- if not self.waitFun then
- self.status = BehaviorStatusEnum.SUCCESS
- return
- end
- if self.waitFun() then
- self.status = BehaviorStatusEnum.SUCCESS
- else
- self.status = BehaviorStatusEnum.RUNNING
- end
- end
|