Implementation Behavior Trees

Mike Kienenberger

Active Member
Contributor
Architecture
GUI
A path consolidator is one improvement. Another one would be to use MoveAlongPath instead of MoveTo. After we move, we don't want to backtrack if we've gone past our intermediate target -- we either want to compute a new path (optimal, but probably too expensive) or at least redetermine what our target node for our current path would be. Maybe a nice compromise would be to compute a new path using our existing path.
 

Mike Kienenberger

Active Member
Contributor
Architecture
GUI
Regarding movement. All of the move code I've seen so far tries to get within .01f of the destination. I initially raised that to .03f in the minions. Honestly, though, .2 or .5 seems like it would be more than sufficient. Do we really need to be more accurate than half-a-block when moving?

Also, I thought I had mentioned this two days ago, but I don't see it above. We need to replace MoveToNode with MoveAlongPathToDestinationNode. Consolidating unnecessary mid-points in a path will help, but we really need to be able to look ahead and determine whether we can skip over certain blocks if we're going fast enough, or start to slow down if we're getting close to a direction change or end point, or, if we've overshot our last target, whether we have to go back to it, or if we can pick a new target at this point.
 

Skaldarnar

Development Lead
Contributor
Art
World
SpecOps
Regarding movement. All of the move code I've seen so far tries to get within .01f of the destination. I initially raised that to .03f in the minions. Honestly, though, .2 or .5 seems like it would be more than sufficient. Do we really need to be more accurate than half-a-block when moving?
I'm not really into your code, but to me it seems that it would be nice to "guarantee" that NPCs reach the destination block (is the destination a block coordinate or can it be any point in between?). Maybe a good example where this becomes necessary is when NPCs are to trigger a pressure plate or something. Thus, .2 or .3 sounds reasonable, .5 may be to inaccurate(?).
 

Mike Kienenberger

Active Member
Contributor
Architecture
GUI
Yes, we can't guarantee an exact destination short of coming to a dead stop and creeping closer, so we need to decide what would be considered "close enough". I'm also thinking .2 for a pressure plate or something like that.
 

synopia

Member
Contributor
Architecture
GUI
While pushing forward L&S, I encountered several issues, that I fixed this weekend:
  • Added icons for jobs, thanks metouto
  • Using Shift while dragging a node creates a copy of the node including all children.
  • Right click on nodes will collapse/expand all children.
  • Select a node and click 'new' will create a new tree with the selected node as a root node. The new tree is available for editing using the dropdown.
  • Lookup node, which runs another behavior tree.
  • Everything you do in editor is saved into a special module 'Behaviors'. Each tree that is loaded from an asset and modified is saved into overrides directory. Each new tree is saved into assets dir. So, when restarting Terasology, everything is reloaded as it was before.
  • Added and tweaked several nodes.
And a small video:
 

synopia

Member
Contributor
Architecture
GUI
Almost a year after I posted the last comment here, Ive made some progress :)

In fact, I rewrote the whole behavior tree thing. Twice. Basically because I am not really happy with the current implementation.

In addition, I have had some bad experiences with developing abstract "frameworks" without having a concrete use case to show its features and verify the usability. So I wrote a small game using libgdx (which has a comparable entity system like terasology), and I finally found some places, where a behavior tree may become handy. This is true for any timed stuff - in the game I use the behavior trees to model the (damage/buff) effects on entities. So instead of having counters and "if (currentTime>duration) {...}"-code all over the place, I use small trees written in json ({ sequence: [{deal_damage:{ base:50, dice:"2D25"}}], {delay:{ duration:0.5 }}, {slow_down: {factor:0.5}}] }).

If someone wants to take a look at it, its in my github, as usual (https://github.com/synopia/tdx). I also assembled some kind of overview documentation there.

The trees can be evaluated in two ways: The simple, direct way by iterating through the tree each tick and by compiling the tree into bytecode. I did some profiling to compare both ways. The performance is more or less equal, but especially for big trees, a lot of memory may be saved for other, more important things. All in all, I am quite unsure, if the compiling stuff is really necessary - but as its really fancy and not *that* complex, I tend to let the code in there and everyone using it, needs to decide which way to take.

Now, I am on integrating everything into terasology, which shouldn't be that much work.
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Bump - I moved this from the Incubator into a Module thread, @synopia I think you managed to fit everything into one without needing additional engine hooks?

I also think this got really close to the integration stage. Just one ... more ... turn! Doooo eeeet! :D
 
Top