Hallo,
while there are several behaviour tree plugins in the Asset Library already, I wanted to have something simpler and quicker to use for prototyping. This is why I wrote this GDScript that should cover most usecases. The tree can be created either by using methods directly:
…or by parsing a text file:
Overall the script expects the user to know what they’re doing; and the code is not thoroughly tested, so if there are any bugs I’d be happy about any reports. A simple video showing it in action:
The behaviour tree supports dynamic parameters now even when constructing the tree from texts (prefix arguments with $ for that). This is probably super expensive performance-wise because you’re basically calling Callables inside a Callable inside a Callable, but I guess it’s okay for testing stuff.
If you create a behaviour tree via text, the script now also accepts a tree node, which either (at the root) creates a sub-tree, or (inside a tree) uses that sub-tree by inserting it. If there’s any interest I would make a simple example for this.
I also added the decorator node ignore, which overrides the result of its child so the result is basically ignored by the parent decorator or composite node. And there’s the nothing node now, works a bit like pass in GDScript.
Wonderful job! I do struggling for write a node based behavior tree a lot. I think this text-based behavior tree can save runtime memory usage to a certain extent.
I roughly went through the code. Here are some suggestion for my point of view.
Scalability
Insted of mannelly define funciton like set_next_pos or walk_to_next_pos, how about use Expression to evaluate those function you write in the text.
For example if I want set a patrol position, instead of write set_next_pos, how about write somethink like:
And you probably want customize the parse process of the property name since the GDScript always passed by value.
In this case:
#Vector2&Color could be some other function call or other thing you can get access base on the actor set_next_pos → set_actor_property(next_patrol_position, “Vector2()”) change_color → set_actor_property(color, ”Color(r, b, b)“)
Debug
Typically debugging takes 80% of my time writing the behavior tree, and it’s important to visualize it and make it simple, especially if your code is very extensible, that will make the behavior tree only executes a very little amount of the code once and once again, and breakpoints just don’t seem like a very desirable way to debug.
I appreciate the suggestion to use expressions for the parameters. I might add an option to use those with another prefix. I don’t think I want to use the Expression class for everything, this feels expensive.
What I definitely wouldn’t want is to change how the tree uses manually defined functions. I find this is the strength of a good behaviour tree, using expressive names. Stuff like set_actor_property(next_patrol_position, “Vector2()”) is verbose, especially as the example function set_next_pos could do much more stuff, like changing the actor’s animation, play a sound effect, etc. If you want to change properties directly it feels like a behaviour tree is the wrong way. You overcomplicate things for the sake of flexibility.
Also be aware that the (simple) text parsing in my script was added as a bonus, kind of. The native way is to add the nodes to the tree directly.
Regarding debugging, the tree script already has a method called generate_string(). If you call it with rich_text set to true and feed it to a RichTextLabel, as seen in my little video, you should have a good overview what the tree is doing.