Discussing Behavior Trees
See original GitHub issueI’ve opened this to discuss behavior trees API enhancements.
@implicit-invocation Resuming discussion https://github.com/libgdx/gdx-ai/pull/4#issuecomment-56509640 … Not sure why you don’t like the XML format, but I think that it has some advantages:
- comments are supported which can be really useful
- it’s more powerful than json or any inline tab-based format.
- being it a standard format, external tools like editors (written in any language) can easily read/write a behavior tree.
So I’m playing with the XML format just to see what can be done. Currently I can successfully load a behavior tree from this file:
<BehaviorTree>
<Import task="com.badlogic.gdx.ai.tests.btree.dogtasks.BarkTask" as="Bark"/>
<Import task="com.badlogic.gdx.ai.tests.btree.dogtasks.CareTask" as="Care"/>
<Import task="com.badlogic.gdx.ai.tests.btree.dogtasks.MarkTask" as="Mark"/>
<Import task="com.badlogic.gdx.ai.tests.btree.dogtasks.RestTask" as="Rest"/>
<Import task="com.badlogic.gdx.ai.tests.btree.dogtasks.WalkTask" as="Walk"/>
<Root>
<Selector>
<Parallel>
<com.badlogic.gdx.ai.tests.btree.dogtasks.CareTask urgentProb="0.8"/>
<AlwaysFail>
<com.badlogic.gdx.ai.tests.btree.dogtasks.RestTask/>
</AlwaysFail>
</Parallel>
<Sequence>
<Bark times="3"/>
<Walk/>
<Bark/> <!-- times defaults to 1, see BarkTask source code -->
<com.badlogic.gdx.ai.tests.btree.dogtasks.MarkTask/>
</Sequence>
</Selector>
</Root>
</BehaviorTree>
I added the “Import” tag to improve readability. It allows you to use the given alias in place of the fully qualified class name of the task. Actually Selector, Parallel, etc… are predefined imports. Also, the “as” attribute is optional, meaning that the simple class name is used as the alias, i.e.
<Import task="com.badlogic.gdx.ai.tests.btree.dogtasks.BarkTask"/>
creates the task alias “BarkTask”. Also, I added task parameters, see urgentProb in CareTask and times in BarkTask. The attribute value is parsed according to the type of the corresponding field of the task class. For example, urgentProb is a float and times is an int. Supported types are: int, Integer, float, Float, boolean, Boolean, long, Long, double, Double, short, Short, char, Character, byte, Byte, and String.
Of course, we can maintain both formalisms as long as they have the same structural features. I mean, unlike task parameters, imports are just a syntactic sugar so they are not mandatory for the inline tab-based formalism.
I think we can use a “btree” branch in order to experiment with BT improvements while keeping the master branch clean.
Issue Analytics
- State:
- Created 9 years ago
- Comments:143 (98 by maintainers)
Top GitHub Comments
I don’t know if it’s the right place to post but I have some suggestions :
First of all I think current API is complete specially with guards and dynamic guard selector, I personally always found a way to implement logic with provided generic tasks without hacking a re-code things (nice job BTW).
My concern right now is about pooling strategy :
My conclusion is that pooling strategy is game specific : recycle whole trees, recycle tasks, don’t recycle is a design choice. But we need a mechanism to allow individual tasks recycling though and I think using Poolable interface is the best choice we have.
@davebaol What do you think ? Did you faced this problem ? I could provide a PR if you don’t have time to implement it but I need your approval first.
@mgsx-dev
I’ve never needed to instantiate/destroy trees in game. I always do it during the initialization phase of the level, but I do recognize your use case. So, yes, PR is welcome. 😄
Sounds good to me
Yeah, this would be an interesting feature. Just notice that when you remove a child the parent task MUST update his own internal status accordingly. This operation is task-specific, of course.
Couldn’t agree more