“本篇文章的非代码部分来源于:https://blog.csdn.net/iamagoodguy_/article/details/39757083
本篇文章的所有代码来源于本博主对原文lua代码的改写&&绿色部分文字是本文新增或修改部分”
转载请保留以上文字
使用BTEditor可以生成行为树(BT,Behaviour Tree)的Lua代码,这里对生成的代码进行解析。
(BTEditor的项目主页:https://github.com/bartoleo/BTEditor)
要注意:
1、行为树每个节点都需要向其父节点返回一个值(可以理解为在执行程序前先通过一个函数来判断JSON数据的子节点是否允许执行),以允许父节点根据子节点运行情况继续运行。
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生成的行为树的代码长成下面这个样子(经过lua table转json后的结果):
//tree
var tree = {
"name": "",
"indexchild": 1,
"height": 50,
"textwidth": 28,
"width": 56,
"children": [{
"name": "Selector_1",
"indexchild": 1,
"height": 50,
"textwidth": 54,
"width": 82,
"children": [
{
"name": "Filter_1",
"indexchild": 1,
"height": 50,
"textwidth": 55,
"width": 83,
"children": [{
"name": "Sequence_1",
"indexchild": 1,
"height": 50,
"textwidth": 62,
"width": 90,
"children": [{
"name": "Action_2",
"indexchild": 1,
"height": 50,
"textwidth": 51,
"width": 79,
"level": 5,
"func": "BuySugar",
"y": 384,
"selected": false,
"valid": true,
"x": 213.15972180497,
"sleep": false,
"id": "node8",
"sim": "",
"textlines": 3,
"type": "Action",
"levelindex": 5
},
{
"name": "Action_3",
"indexchild": 2,
"height": 50,
"textwidth": 44,
"width": 72,
"level": 5,
"func": "BuyCar",
"y": 384,
"selected": false,
"valid": true,
"x": 328.65972180497,
"sleep": false,
"id": "node9",
"sim": "",
"textlines": 3,
"type": "Action",
"levelindex": 6
}
],
"level": 4,
"func": "",
"y": 288,
"selected": false,
"valid": true,
"x": 261.90972180497,
"sleep": false,
"id": "node7",
"sim": "",
"textlines": 3,
"type": "Sequence",
"levelindex": 4
}],
"level": 3,
"func": "HasMoney",
"y": 192,
"selected": false,
"valid": true,
"x": 265.40972180497,
"sleep": false,
"id": "node2",
"sim": "",
"textlines": 3,
"type": "Filter",
"levelindex": 3
},
{
"name": "Sleepy",
"indexchild": 2,
"height": 50,
"textwidth": 49,
"width": 117,
"level": 3,
"func": "Rest",
"y": 192,
"selected": false,
"valid": true,
"x": 363.75957639191,
"sleep": false,
"id": "node6",
"sim": "",
"textlines": 3,
"type": "Condition",
"levelindex": 7
},
{
"name": "Action_3",
"indexchild": 3,
"height": 50,
"textwidth": 47,
"width": 75,
"level": 3,
"func": "GoHome",
"y": 192,
"selected": true,
"valid": true,
"x": 515.59027819503,
"sleep": false,
"id": "node5",
"sim": "",
"textlines": 3,
"type": "Action",
"levelindex": 8
}
],
"level": 2,
"func": "",
"y": 96,
"selected": false,
"valid": true,
"x": 387,
"sleep": false,
"id": "node1",
"sim": "",
"textlines": 3,
"type": "Selector",
"levelindex": 2
}],
"level": 1,
"func": "",
"selected": false,
"valid": true,
"y": 0,
"x": 400,
"id": "__start__",
"sleep": false,
"textlines": 3,
"type": "Start",
"levelindex": 1
};
现在根据上面的规则来进行代码编写即可。
我写了一个,没有完整实现,并且约定Condition条件判断的函数名使用name来指定。代码如下:
// 如果有钱了,就买糖、买车;
// 否则,需要回家取钱,如果累了,则休息(可能休息后会回家吧),如果不累,就回家取钱!
//================并且约定Condition条件判断的函数名使用name来指定
var obj;
var ipairs = function(obj) {
if (obj) {
return obj;
} else {
return {};
}
}
var BT = {
//-- 1、调用前保证BT中的函数全部都在obj表中
//-- 2、假设输入合法
run: function(bt, object) {
obj = object;
var first_children = bt.children[0];
console.log("first::",first_children.type)
BT[first_children.type](first_children);
},
// -- Composite Node
//-- Selector
Selector(node) {
var return_value = false;
let childArray=ipairs(node.children);
for (var child in childArray) {
var childValue = node.children[child];
console.log("Selecter type:",childValue.type)
//调用filter
if (BT[childValue.type](childValue) == true) {
console.log("Selecter type: true:",childValue.type)
return_value = true;
break;
}
}
return return_value; //因为【当前函数】是在上一级函数里面调用的,所以等同“告诉上一级流程是否为true或者false”
},
//-- Sequence,标记为:"并列的动作
Sequence(node) {
var return_value = true;
console.log("Sequence:1=》2=》3",ipairs(node.children).length)
let childArray=ipairs(node.children);
for (var child in childArray) {
var childValue = childArray[child];
console.log("Sequence type:",childValue.type,"~function:",childValue.func)
//调用action
if (BT[childValue.type](childValue) == false) {
return_value = false;
break;
}
}
return return_value; //因为【当前函数】是在上一级函数里面调用的,所以等同“告诉上一级流程是否为true或者false”
},
//-- Behaviour Node
//-- Action
Action(node) {
obj[node.func]();
return true;
},
//-- Condition Action
Condition(node) {
if (obj[node.name]()) {
obj[node.func]();
return true;
} else {
return false; //因为【当前函数】是在上一级函数里面调用的,所以等同“告诉上一级流程是否为true或者false”
}
},
//-- Decorator Node
//-- Yet nothing ...
//-- Condition Node
//-- Filter,过滤,如果满足条件才继续,否则就中断
Filter(node) {
console.log("Filtr:",node.func)
//执行统一层级的条件判断
if (obj[node.func]()) {
var first_children = node.children[0];
BT[first_children.type](first_children);//执行指定【类型】函数
return true;
} else {
return false; //因为【当前函数】是在上一级函数里面调用的,所以等同“告诉上一级流程是否为true或者false”
}
}
};
测试代码如下:
var person = {
HasMoney: function() { return false },
Sleepy: function() { return false },
Rest: function() { console.log('rest') },
BuyCar: function() { console.log('buy car') },
BuySugar: function() { console.log('buy sugar') },
GoHome: function() { console.log('go home') },
}
BT.run(tree, person);
修改上面的HasMoney和Sleepy的返回值,可以得到不同的行为结果。
在线源码阅读:点击跳转
更多相关参考:
https://blog.csdn.net/xufeng0991/article/details/60137670
https://www.indienova.com/indie-game-development/ai-behavior-trees-how-they-work/#iah-6
明明不是原创为啥选原创!!还要不要脸!!
1.博客对非原创文章特不友好,故意选的原创
2.javascript版本的行为树相关解释太少,对H5开发者不友好,故选原创
3.博主有私心,故选原创
4.如果对任何人产生了不利影响,请联系博主,评论在下方。
---------------------------------------------------------------------------------------------瑟瑟发抖ヽ(*。>Д<)o゜
下一篇点击访问