[AI SCRIPTING] Panda BT: Behaviour Tree scripting

Hi guys!

Panda BT is script-based Behaviour Tree engine. It allows you to easily write complex and scalable logics for your games.

Here are the main features:

  • Lightweight and performant Behaviour Tree engine.
  • Minimalist Built-in scripting language.
  • Easily extensible by defining custom tasks in C#.
  • Realtime visualization and debugging.
  • Version control friendly (produces no binary assets).

A typical work flow is as follow:

  • Define simple tasks as C# methods in MonoBehaviours.
  • Use the defined tasks as building block for writing BT scripts.
  • Visualize the BT as it is running to have insight about how your AI is performing.

Here is a screenshot of the Panda Behaviour component running a BT script:


You can read the online documentation and try some demos on the Panda Behaviour website.

Please let me know what do you think about it, how it is useful to you or what would you expect as improvements.

Eric

5 Likes

The demos look really nice, especially being able to follow the tree execution inside the game window! Do I understand this correctly: trees are edited in text files, which can then be dragged onto a panda component?

2 Likes

Thanks for your feedback!

The visualization of tree execution is a great way to know exactly what’s going on. It’s also available in the Inspector.

Yes, that’s the way to use this component. You can also assigned several script files to the same PandaBehaviour component for better organisation. For example, you can have a script file used as a behaviour library, and another script file that implement the main BT.

This is a really good asset, not tricky to understand and master at all! Keep up the good work :slight_smile:

1 Like

Thank you @Jamster ! I’m glad you understand it and even master it!
I am actually worried about the learning curve of my tool. It’s reassuring you have no difficulties to learn how to use it.:slight_smile:

I don’t think it’s too hard to learn at all, perhaps more documentation on things like the Task.current wouldn’t go amiss however as it took me a while to work out what that was doing with that.

One thing that could be thought upon (though I’m not sure how you’d do it now it’s released) is a more firm syntax. I think it’s just me being used to C like languages but for the while loop it seems a little odd that the condition looks almost exactly the same as the body, the only difference being that they’re on different lines. Another is that functions can have parenthesis or no parenthesis though that’s easily solved by just adding parenthesis everywhere :stuck_out_tongue:

Nonetheless, a very good piece of code, seems fast enough running in practice and it’s pretty flexible. I’m not sure if I’ll use it in my current project (not that I know where that project is going at all) just because for the most part in my particular use I could do everything I’d do in Panda by just adding a line of code to Update. Though I’ll definitely keep it in mind for the future :slight_smile:

May I also ask how it works inside the dll? Are you constructing a tree/fsm internally in Awake/Start or are you parsing the text as you go? If constructing a tree can we access the tree from code? :slight_smile:

Jamie

Task.current

Task.current is consequence of using methods as task implementations rather than classes. It would have been more tedious to define a new class each time a new task is required. But this construction is indeed a bit exotic if you expect an OOP architecture. Task.current is a key object, I will put more focus on its importance in the documentation or future tutorials. Thanks for your feedback on this important point.

About the syntax

About the syntax, if you have an idea about what would be more appropriate please tell me! And don’t worry about it’s already released; it’s always possible to implement a versioning.

The language is different from existing languages indeed (except for the indentation which is similar to Python). In fact, I’ve started with the idea to define the BT directly in C#, but I couldn’t come up with a satisfying API that would make the BT both simple to write and easy to read. That’s why I went in the direction of defining a new scripting language. A positive byproduct of that solution is the realtime visualization: that would have been impossible or really hard to implement in a C#-only solution.

The basic principles behind the syntax are:

  • Everything is a node (tree, sequence, while, fallback, task, …)
  • A node can have parameters (which type can be: boolean, int, float or string)
  • A node can have other nodes as children.

Following this principle, the condition and the body are indeed both children of the while node, only their order distinct them from each other. The first child is the condition, the second child is the body. However, it’s possible to make a visual distinction between the condition and the body by using indentation or single line parenting.

For example:

// This...
while
    condition
    body

// ...is the same as
while condition
    body

Side note: while is not a loop (in Panda)

I know it sounds confusing, but the while node is not a loop but a conditional node. The only node that implements looping is the repeat node.

Let’s clarify that with examples.

(The syntax highlighting is not meaningful here, it’s just that C# highlighting is applied… I’m dreaming about having a dedicated Panda syntax highlighting, :wink: at the forum maintainers)

For example the following construction is not a loop, but it’s rather a condition:

 // Start the engine and drive until the tank is empty.
while hasGass
   sequence
       StartEngine
       Drive

The while node is used to run a node under a satisfied assumption. We start the engine only once, then we keep driving while we have gass. There is no repetition.

The equivalent of the while loop of other programming language is implemented with the combination of the while node and the repeat node:

 // Shoot at the target several times as long as we have bullets.
while hasBullets
    reapeat
        sequence
           AimAtTarget
           Shoot

Here we repeat at aiming and shooting at the target while we have bullets. The aiming and shooting are repeated.

Internals

The script is not parsed as the BT is executed, it’s parsed only once. A tree is indeed constructed as the result of the parsing.

I tried to exposed the minimum of the internal functioning to the user (encapsulation principle). It’s possible to access the internal tree from code, but that’s not documented. Do you think there are use cases to have it exposed through the API, or are you just curious?:slight_smile:

1 Like

Interesting, I definitely think that that information should (mostly) all be in the docs (it may be in there, I’ll be honest I mainly used the examples to learn!) :slight_smile:

My thoughts were that if something were to return a condition affecting the statement before then it should be in brackets (or something) like:

while (condition)
    body

but actually I’d disagree with myself now because to follow it you need nodes such as:

fallback
    (a)
    (b)

repeat
    (sequence
        a
        b)

Which isn’t so nice…

I think that the best solution is actually the inline children as you setup, it looks a lot better than my idea!

I was mainly being curious, I suppose there could be times where it would be nice to load in behaviours from the internet (for modding prehaps) but I doubt that being able to access the tree would have huge value.

Jamie :slight_smile:

Also the condition can be any node, even a complete tree!
So you can have structure like this.

// Drink while glass is not empty *and* still thirsty
while
     sequence // condition
        not IsGlassEmpty
        IsThirsty
     repeat // action
         sequence
             GrabGlass
             Drink
             PutGlassDown

Here the sequence is used to implement an AND logic.

There was someone who was looking for a solution to make a game where the players would write their own AIs and let them battle each other (I couldn’t find back his post). He was looking for a solution that would allow the edition and compilation of the BT at run-time. Panda is suitable for this usage. For now, a TextAsset is required to store the BT script. But maybe I could expose an API to build BT directly from a string.

2 Likes

Hey Eric,
Great tool, I would like to request access to the sources of the tool you are providing (already wrote a review on the AssetStore). I don’t mind paying for it.
Keep the good work.

Hi Georges,

Thank you for your interest in my package and for your review on the Asset Store.

I had the intention to release a paid/pro version on the Asset Store, after receiving feedbacks from users and after implementing eventual improvements. However, after several pressing requests to have access to the sources, I decided to include the sources in the pro version, and release it earlier than planned. So, stay tuned!

It the meantime you can use the free version. The BT scripts made with the free version will be compatible with the pro version without issue.

2 Likes

I’ll update the review again.
Regards! :slight_smile:

Looks nice. Any possibility of wrangling VS to do some auto complete and compile time checking of .BT files?

I haven’t the foggiest clue of how to approach this.

Thank you @Kiwasi ! Great you had some time to have a look at it.

Excellent point. That’s where there is a big space for improvement. Editing the BT scripts as plain text without a standard IDE support is not ideal. Even if the BT language is simple, having syntax highlighting and auto-completion in Visual Studio would be a productivity helper.

It seems possible to develop plugins for VS to support custom languages. However, it seems to be a complete project in itself. If anyone has experience with this topic any input would be welcome.

In any case, this is something on the top of my to-do-list.

About compile time checking of BT script. The scripts are already checked when they are modified but only for the current opened scene. I’ve planned to implement a project-wise checking when the scripts get imported as assets.

I spoke too soon on that one, a few minutes later the console spit out an error in my BT. Nice work.

So so far so good. Just putting together a space invaders clone to see how the thing works. Will let you know in a couple of hours how it went.

A small editor that let you add/remove nodes/tasks directly on the Inspector (where the BT is visible) and furthermore drag/drop/move/cut/copy/past nodes/tasks on it would be great additions in the future. :smile:
If I ever get the time, I’ll work on it (would need sources for that btw). :wink:

1 Like

Sounds great. I am really curious about the result.
Meanwhile, let me know if you have issue in the making of this game.

I’ve been always considering an all-in-inspector editor, it sounds as good idea but I’m worried about how practical it would be. It seems difficult to have a satisfying solution combining both a drag-and-drop editing style and code typing style. It’s seems this design would lead to some sort of advanced text editor in the inspector. I’m not sure about doing everything in the inspector, you need to edit your C# code externally anyway. So I rather leaning towards adding support to a trustworthy external tool such as VS.

But your are welcome if you have suggestions, or eventual implementations. (btw, the sources are on their way to the Asset Store).

1 Like

Games done. A couple of things I noticed

  • Multi object editing would be nice.
  • Wait 100 counts down in ticks instead of seconds. Wait 100.0 counts down in seconds. Is this desired behavior? Should be in the docs.
  • Selecting an object in the hierarchy seems to reset the behavior tree on that object

Anyway, I had fun with this. Thanks for putting it together. I’m probably going to use it heavily in some of my future work.

You can check out the game here.
Let me know if seeing how I used your asset would be useful, I can send source.

That was fast!

Thank you for your feedback.

  • I take note about multi object editing.
  • Task definition can be overloaded. There are indeed two versions of the “Wait” task and they work as you’ve described on purpose (maybe I should drop the ticks version, I’m not sure). There are other build-in tasks (implemented int the Panda Behaviour component) and that definitely need to be documented. Sorry about that. BTW, If you have suggestions about other built-in tasks, your are welcome.
  • I’ll have a look about that resetting bug.

I’m glad you like it and are planning to use it further!

The games look nice and play smoothly. About the game-play itself, I feel the ship should move faster. Also you should be able to shoot again as soon the bullet hits an enemy or has leaved the screen.

Of course I’m curious about how you’ve made it, please send it to me.:slight_smile:

Edit:
The resetting bug is fixed. There is already a package review pending, therefore this fix won’t be in the next release, but the one after.