您的位置:首页 > 其它

二、行为树的原理和实现

2014-10-03 18:18 239 查看
使用BTEditor可以生成行为树(BT,Behaviour Tree)的Lua代码,这里对生成的代码进行解析。

(BTEditor的项目主页:https://github.com/bartoleo/BTEditor)

要注意:

1、行为树每个节点都需要向其父节点返回一个值,以允许父节点根据子节点运行情况继续运行。

2、每棵树都有一个根节点,这个节点没有特殊意义。

需要解析的行为树节点的解释(发挥想象力吧,这里的Node还能有很多种~):

一、Composite Node

1、Selector:实现子节点或关系,按定义顺序遍历子节点,直到有一个子节点返回true时停止,并返回true。如果子节点全部返回false,则返回false。

2、RandomSelector:类似Selector,不同之处在于,按照随机顺序遍历子节点。

3、Sequence:实现子节点与关系,按定义顺序遍历子节点,直到有一个节点返回false时停止,并返回false。如果子节点全部返回true,则返回true。

4、Parallel:实现逗号表达式的效果,依次执行所有子节点,返回最后一个子节点的返回值。

5、。。。

二、Behaviour Node

1、Action:执行其中定义的行为,并返回true。

2、ConditionAction:如果条件为真,则执行Action,并返回true;否则,不执行Action,并返回false。

3、。。。

三、Decorator Node

1、Successor:拥有一个子节点,执行子节点后返回true。

2、Failure:拥有一个子节点,执行子节点后返回false。

3、Negate:拥有一个子节点,返回子节点返回值的相反之(true变false,false变true)。

4、。。。

四、Condition Node

1、Filter:如果Filter为真,则执行子节点,并返回true;否则,不执行子节点,返回false。

2、。。。

下面来看看BTEditor:

例子,如果有钱了,就买糖、买车;否则,需要回家取钱,如果累了,则休息(可能休息后会回家吧),如果不累,就回家取钱!

长成这样:



BTEditor生成的行为树的代码长成下面这个样子(经过简化):

return {
nodes={
{
children={
{
children={
{
children={
{
children={
{
func="BuySugar",
name="Action_2",
type="Action",
},
{
func="BuyCar",
name="Action_3",
type="Action",
}
},
func="",
name="Sequence_1",
type="Sequence",
}
},
func="HasMoney",
name="Filter_1",
type="Filter",
},
{
func="Rest",
name="Sleepy",
type="Condition",
},
{
func="GoHome",
name="Action_3",
type="Action",
}
},
func="",
name="Selector_1",
type="Selector",
}
},
func="",
name="",
type="Start",
}
},
}


现在根据上面的规则来进行代码编写即可。

我写了一个,没有完整实现,并且约定Condition条件判断的函数名使用name来指定。代码如下:

local BT = {}
local obj

-- 1、调用前保证BT中的函数全部都在obj表中
-- 2、假设输入合法
function BT.run(bt, object)
obj = object
local first_children = bt.nodes[1].children[1]
BT[first_children.type](first_children)
end

-- Composite Node
-- Selector
function BT.Selector(node)
local return_value = false
for _, child in ipairs(node.children) do
if BT[child.type](child) == true then
return_value = true
break
end
end
return return_value
end
-- Sequence
function BT.Sequence(node)
local return_value = true
for _, child in ipairs(node.children) do
if BT[child.type](child) == false then
return_value = false
break
end
end
return return_value
end

-- Behaviour Node
-- Action
function BT.Action(node)
obj[node.func]()
return true
end
-- Condition Action
function BT.Condition(node)
if obj[node.name]() then
obj[node.func]()
return true
else
return false
end
end

-- Decorator Node
-- Yet nothing ...

-- Condition Node
-- Filter
function BT.Filter(node)
if obj[node.func]() then
local first_children = node.children[1]
BT[first_children.type](first_children)
return true
else
return false
end
end

return BT


测试代码如下:

local BT = require('bt')
local tree = require('bt_unittest_input')
local person =
{
HasMoney = function() return false end,
Sleepy = function() return false end,
Rest = function() print('rest') end,
BuyCar = function() print('buy car') end,
BuySugar = function() print('buy sugar') end,
GoHome = function() print('go home') end,
}
for i = 1, 2 do
BT.run(tree, person)
end

修改上面的HasMoney和Sleepy的返回值,可以得到不同的行为结果。

代码下载:http://pan.baidu.com/s/1ntn1NTJ
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: