MonoBehaviourTree — Simple event driven behaviour tree

This project started because I couldn’t find any free, decent behaviour tree asset meeting requirements of game I am currently working on, but at some point I realized it might be good idea to share it for free.
It is far from perfect and I am aware of many mistakes I made on my road, but if this tool help any of you I would be more than happy.
Github repo: GitHub - Qriva/MonoBehaviourTree: Simple event driven Behaviour tree for Unity projects
Asset store: https://assetstore.unity.com/packages/tools/ai/monobehaviourtree-213452
Asset thread: MonoBehaviourTree - Simple event driven behaviour tree

Anyway, I came here mainly to get some feedback and these are questions I am interested in:

  • Is this tool any usefull in real world scenario?
  • Is there something important missing or broken?
  • Do you think it is worth to rewrite it using Graph View API (when released) in near future?
    If yes, then what should be reworked/improved in 2.0 version?

Any other feedback or contribution strongly appreciated!

Features:

  • Visual editor

  • Event driven BT

  • Built-in blackboard with observable variables

  • Easy creation of custom nodes and variables

  • Logic can be stored in prefabs (based on components)

  • Almost GC free

  • Breakpoints

  • Playmode flow and state debugging

Plans / Roadmap:

  • Adding more of commonly used nodes

  • Reworking node names to autogenerated [under consideration]

  • Creating package or releasing on asset store if this tool is considered useful

  • Rewriting to graph view

1 Like

Update: MonoBehaviourTree can be installed now via package manager using following url:

https://github.com/Qriva/MonoBehaviourTree.git#upm

I do looking for BT, one of good free asset in store is Eliot AI, the node design was good, not really normal BT, but it is abandoned, no luck to fix it, only work in editor! on build not work, but you can check it‘s node design.

Update: Released in asset store: MonoBehaviourTree | Behavior AI | Unity Asset Store

1 Like

Quite a nice project so far!
Been lately looking at a couple of the tree solutions and even started writing my own for fun to learn about what really matters, since I too haven’t found very good free solutions and on the fence whether to spend those 80$ on the top notch solution out there…

Your implementation is neat and slim! The editor is fine, not sure rewriting to the new Unity api would be worth it, however I’d wish for the possibility to visualize some internal state within the view. At least one or two lines. Of course it might be troublesome when the nodes do not all have the same size anymore unfortunately, but it’d help in many debugging cases where you do not want to click every node separately.
Simple example: Seeing the number of repeats left in a repeater node.

Another suggestion: When clicking in the behavior tree window, it’d be nice if the inspector window would automatically jump to the game object that holds the tree.

Btw. it might be neat to link this thread in your entry on the asset store. People like to have a support thread, even if you won’t answer all that much etc. as it’s a free project.

One thing that makes me wonder, why exactly are the nodes monobehaviors?
When I first read the description of your project, I thought one would need to pull every single node as a script onto an object in the hierarchy (as that’s why you usually use monobehaviors), but that’s not the case from what I see in the examples. The nodes do exist “virtually” without a separate, real game object except for the singular one that contains the main script and blackboard, right?
Is it just so we can use the update and start method somehow if we wanted to? That’s not really typical for BTs after all.

Thing is, monobehaviors have a bit of an overhead (especially regarding code reload time because Unity interprets them in a special way) and sometimes you want to instantiate BTs for many enemy entities for example.

Last but not least, the sub-tree approach is a bit suboptimal unfortunately. Modularity is one of the big strengths of BTs and actual modularity needs the possibility to re-use the same sub-tree independently from its instances. Your tight coupling between parent and child trees unfortunately does not allow for that.
Furthermore what if I want the same tree on 10 enemies that otherwise are very different? Could perhaps work with nested prefabs, but that’s not the smoothest workflow for this.

How about if instead, just like your Monobehavior nodes are virtualized, you make the whole tree virtual?
Instead of tying the actual tree instance to an object, let that work as if the game objects with a tree were like files: Game objects that can be anywhere in the hierarchy each have a tree.
Or even better: Make them scriptable objects!
Then your MBT executor script takes a reference to that MBT instance (or just the scriptable object) like before, however instead of actually using that linked instance, a new, copied instance of the tree shall be generated upon start (ideally from a pool or buffered).

Finally the MBT Executor would get a button like “view tree” that tells the Behavior Tree window which virtual instance to show. Or you can give the window a dropdown menu with all executing instances.
This would allow to reference the same sub-tree in multiple main trees seamlessly too.

The result of this would be that the game objects with the actual tree are only there for designing and debugging. With that you could even offer a “build mode” where the file-like game objects are just destroyed upon launch for maximum performance.
If you use scriptable objects, that can even be omitted as a whole of course.

EDIT: The more I think about it the more I find “ScriptableObjectTree” would be an ideal way (if you don’t wanna introduce your own file format etc. like the commercial big players), even if it does not have the same ring to it :stuck_out_tongue:

Now I wrote way more than intended, haha.
Am looking forward to what you do with this project in every case :slight_smile:

1 Like

Thank you very much for the feedback!

Right! Actually I forgot I could create thread in asset store section.

Actually this is the main reason why I am not so happy - simply bad design choice. I can’t remember exact reason, if that was my lack of knowlege about scriptables or maybe to make it easy for me to keep state of each node separately, or it evolved from something else.

In any case I agree with most of what you wrote and these are consequences of how everything is structured.
If I had to rewrite this again I would make it more like animator - single asset as tree and some executor mono running it and keeping internal state inside, while graph itself is just stateles template. In addition I would like to design blackboard a bit better and variable injection.

To summarize I would like to write version 2.0, but only if it’s worth it - I mean if there are people with need of such a tool, otherwise it would be probably waste of time.

Phew, hard question. In the end, almost everything that’s a popular programming technique exists in Unity in some shape or form already and there are a handful of free solutions and ones < 20$ too. So you have to provide an advantage over others to be worth it.
Having a nice editor is already an advantage that might make it worth it to go for a 2.0 if you can reuse much of that part.

Well, I could write it on jobs or something, but I don’t think it is possible as many nodes require access to outer objects or to call methods directly. I think the best improvement I can do is better modularity and graph editor.

Burst is something I was considering too, but gave up that idea quickly. Burst is best when you want to manage some mass of data. Yeah, you cannot access the Unity API and managed instances from inside a job and that’s what the majority of nodes do, so likely not a worth approach.
Still there’s much one can do in regards of performance like a data driven approach and maybe provide a way so the nodes can decide themselves how often they need to be ticked.
So for example the wait node can work without a busy-waiting style of timer.

Good plan.

1 Like