Modular Behavior Tree
A JavaScript implementation of modular behavior trees, similar to Lumberyard engine's MBTs. This library has been highly inspired by these two existing libs: BehaviorTree.js and BEHAVIOR3JS.
Features
- Load trees from XML files
- Basic composite, decorator and action nodes included
- Blackboard to access global data
- Create your own nodes
Installation
npm install --save modular-behavior-tree
Example
subtree1.xml
subtree2.xml
maintree.xml
index.js
;// defining custom action{superproperties}{}{ifthispropertiestextconsolereturn SUCCESS}{}// loading trees from XML fileslet subtree1 = BehaviorTreelet subtree2 = BehaviorTreelet mainTree = BehaviorTree// create behavior tree instancevar bt = tree: mainTree blackboard: someVariable: 123// call bt.tick() for tree execution
Manual trees mixed with parsed trees
You can create your trees directly without parsing a XML file and even mix them together with XML parsed trees.
let subtree = BehaviorTree let tree = nodes: { console return FAILURE } subtree
Register custom nodes and trees
To make the tree loader aware of subtrees or custom nodes you have to pass them as second argument into the parse function.
// custom node // ... // subtreelet subtree = BehaviorTree // main tree with passed custom node and subtreelet maintree = BehaviorTree
Basic Nodes
This library ships with some basic nodes to get your started.
Sequence, Selector, MemSequence, MemSelector
Composite nodes with children. Mem* does remember the last executed child which returned RUNNING and will not executed the previous children.
Inverter
SUCCESS -> FAILURE, FAILURE -> SUCCESS
MaxTime
Returns FAILURE if the child takes too long. Makes sure that the child returns RUNNING as long as it's computation is still running.
Wait
A simple wait action, which returns RUNNING as long the time is not over yet.
Constants
Use following constants as return value for the run method
- SUCCESS: computation succeeded
- FAILURE: computation failed
- RUNNING: computation still running
Methods
start
- called before run is called, but not if node is resuming after ending with RUNNINGend
- called after run finishes with SUCCES or FAILURErun
- main computation function
Defining own nodes
You have to inherit from one of these 4 classes, if you want to create your own node:
Action, Composite, Decorator, Condition
Mostly you will be fine to go with inheritance of Action
Action
{superproperties}{ifthispropertiestextconsolereturn SUCCESS}
In case you are planing to create additional composites or decorators you can have a look how the basic ones are implemented, ...
Sequence
{superchildren}{for let i=0; i<thischildrenlength; i++let status = thischildreni;if status !== SUCCESS return status;return SUCCESS;}
Selector
{superchildren}{for let i=0; i<thischildrenlength; i++let status = thischildreni;if status !== FAILURE return status;return FAILURE;}
MemSequence
{ super children this_openNodeIndex = null } { for let i=0; i<thischildrenlength; i++ if!this_openNodeIndex || this_openNodeIndex && this_openNodeIndex === i let status = thischildreni; this_openNodeIndex = status === RUNNING ? i : null if status !== SUCCESS return status; return SUCCESS; }
MemSelector
{ super children this_openNodeIndex = null } { for let i=0; i<thischildrenlength; i++ if!this_openNodeIndex || this_openNodeIndex && this_openNodeIndex === i let status = thischildreni; this_openNodeIndex = status === RUNNING ? i : null if status !== FAILURE return status; return FAILURE; }
Inverter
{ super child } { if !thischild throw "No child defined for Inverter" let status = thischild }
Version history
- 1.0.4 - async/await support
- 1.0.3 - updated dependencies
- 1.0.2 - add links, update readme
- 1.0.1 - new bundle
- 1.0.0 - initial release