owl-bt is editor for Behavior trees. It has been inspired by Unreal engine behavior trees in a way, that it supports special node items like decorators and services. This makes trees smaller and much more readable.
owl-bt has been created because we needed a behavior tree editor for our game Tendril: Echo Received, where we are focusing on live npc behavior.
We have tried some of the existing solutions, but they haven't meet our requirements like:
npm install owl-bt -g
owlbt -h
cd <project-dir>
owlbt i
owlbt c <tree-path>
owlbt o path
owl-bt runs as a service on port 8955
by default. This can be changed in config file .owlbtrc
, that must be created in the user`s home directory.
{
"port" : 1234
}
In owl-bt, there are three types of items:
ctrl+shift+p
Project file (owl-bt.json
) defines all nodes and node item types that can be used in trees.
fa-
prefix){{PropertyName}}
fa-
prefix){{PropertyName}}
fa-
prefix){{PropertyName}}
Enables to define custom property types
Example:
{
"types":{
"myString" : {
"type" : "string",
"pattern" : "v[0-9]"
}
},
"nodes": [
{
"name": "SetAlertLevel",
"icon": "exclamation",
"description": "Set alert level to "{{Level}}"",
"isComposite": false,
"properties": [
{
"name": "Level",
"default": "None",
"type": "enum",
"values": [
"None",
"Investigate",
"HighAlert",
"Panic"
]
}
]
}
],
"decorators": [
{
"name": "HasZoneReportedEnemy",
"icon": "phone",
"properties": [
{
"name": "MaxReportAge",
"default": 1,
"type": "number"
}
]
}
],
"services": [
{
"name": "ReadPlayerPos",
"icon": "pencil",
"description": "Store player pos to "{{BlackboardKey}}"",
"properties": [
{
"name": "BlackboardKey",
"default": "Target",
"type": "string"
}
]
}
]
}
{
"type": "Selector",
"name": "rootNode",
"childNodes": [
{
"type": "Sequence",
"services": [
{
"type": "Sample service"
}
],
"decorators": [
{
"type": "IsBlackboardValueSet",
"properties": [
{
"name": "Field",
"value": "myValue"
}
],
"periodic": true
}
]
}
]
}
It is possible to derive a node item type from another type using base
setting.
It is possible to use string
or array of strings
for base
setting. In case of array, base item types are applied in a specified order. That means, that the later item type overrides item specified before it.
E.q. we may create a base node:
{
"name": "MyBaseNode",
"icon": "arrow-right",
"color": "red",
"isAbstract" : true,
"properties": [
{
"name": "prop-from-base1",
"type": "string"
},
{
"name": "prop-from-base2",
"type": "number"
}
]
},
And derived node:
{
"name": "MyDerivedNode",
"color": "blue",
"base": "MyBaseNode",
"properties": [
{
"name": "prop1",
"type": "string"
},
{
"name": "prop-from-base2",
"default" : "abc",
"type": "string"
}
]
},
Resulting node after applying inheritance is going to look like:
{
"name": "MyDerivedNode",
"icon": "arrow-right",
"color": "blue",
"base": "MyBaseNode",
"properties": [
{
"name": "prop-from-base1",
"type": "string"
},
{
"name": "prop-from-base2",
"default" : "abc",
"type": "string"
},
{
"name": "prop1",
"type": "string"
}
]
},
owl-bt.js
file in the same directory as project file owl-bt.json
is considered plugin.
Plugin js file exports object with plugin functions.
module.exports = {
onTreeSave: ({ tree, path, project, projectPath }) => {
},
onTreeLoad: ({ tree, path, project, projectPath }) => {
}
}
onTreeSave
- executed before the tree json file is saved to disk. Only modifications of tree
object are allowed.
tree
- tree object (according to tree json file)path
- tree file pathproject
- project object (according to owl-bt.json
file)projectPath
- project file pathreturn
- when the return value is false
or a string, then the save is prevented and error is returned to clientonTreeLoad
- executed after loading tree json file from disk. Only modifications of tree
object are allowed.
tree
- tree object (according to tree json file)path
- tree file pathproject
- project object (according to owl-bt.json
file)projectPath
- project file pathIt is possible for example to
create a custom tree file formats using onTreeSave
and onTreeLoad
.
If we wanted to have project path stored in the tree file, we could create the following plugin:
module.exports = {
onTreeSave: ({ tree, path, project, projectPath }) => {
tree.projectPath = projectPath;
}
}
base
and isAbstract
properties in project definitionctrl+shift+p
->'core:Set Node Type'
or rmb
->'Set Node Type'
)