Comments (11)
Thanks for your great addons! I have being using it for a couple of weeks, and still looking forward to more future updates.
Recently I am developing a tool, which uses Xmind and excel as an tree editor and create behavior tree dynamically in run-time, mostly based on your addons.
That helps my work a lot. Therefore I am introducing your addons to my Godot developer friends in China, and they show great interest too.
May I have your email or other contacts and learn some more about AI? Thanks.
from godot-behavior-tree.
I see what you mean.
If you want to make a branch conditional, you put it under a decorator, extend the decorator and define your condition there (as it's done in the example), but if your sequence (or any other node) is in a running state it can't be interrupted until completion, at least not in a straightforward way.
I will definitely work on making this possible, maybe with an event driven approach as it's done in Unreal.
Thank you for bringing it up, this is a work in progress and I'm trying to improve it everyday!
Allowing abortion will require some design changes so it may take a bit longer than other smaller improvements I have planned.
The best thing you could do until I implement this, is to put your 'states' (wandering, attacking, etc.) under a Parallel node and enclose them in a decorator. A parallel node allows you to execute all the children regardless of result and without waiting for execution.
Something like this:
Obviously there are a few extra steps to this solution: because it won't abort the previous sequence, you may have overlapping behavior. So it depends on how things are on your end, but if you are just waiting you can put another condition after the wait is completed to check if you are still in, say, 'wandering state' and return fail() if you are not, so the sequence doesn't continue.
Another thing is putting a while loop inside your decorator and keep ticking as long as 'wandering' is true.
So ultimately, you have a lot of control over how you design it: my suggestion is to prefer short, repeated actions rather than tasks that take very long to complete. This is the way I see a behavior tree should be designed, but what you suggested is definitely something that other implementations have and that should be possible for the user to do.
Also keep in mind that using the Behavior Tree like this makes it kinda like a state machine. So if you wanna design things in that way, a state machine is probably more suitable (I recommend https://gitlab.com/atnb/xsm)
from godot-behavior-tree.
Yeah, trying parallel nodes, I was able to develop some AI which addressed my problem reasonably well. I think taking your advice of thinking about behaviour trees less in the terms of finte state machines helps too. I am fairly new to them. That said, I still think there's value in the Unreal-style approach of branch aborting, especially as trees start to balloon in complexity.
from godot-behavior-tree.
Good :) Parallels are the "worst" in terms of performance so, if you can, think of other ways.
Always happy to provide support if you need! I know it's not very user friendly yet but I'm actively trying to improve it and make it as complete and powerful as possible.
I'm onto the flow abortion now so it will be a thing in the next update. Also, the way running states are handled will change with it, so I'm gonna have to make sure the update doesn't break your behavior trees.
from godot-behavior-tree.
It's amazing to see this! I'm glad my addon turned out useful and I'm excited to see what you've done with it.
My email is [email protected] or if you want you can find me on Discord at kagenashi#8224
(By the way, this is not really an issue nor it is related to the issue above, so next time open a new discussion instead)
from godot-behavior-tree.
This issue will be addressed in the 1.2.rc4 version.
from godot-behavior-tree.
Nice!
from godot-behavior-tree.
I have started updating the 1.2.rc4 branch. There are some changes already, although the features is not there yet. However, I made a much more complex example to show how to achieve some of the behaviors you people were talking about!
That shows how the tree can be made responsive and flexible. I think that even without a "interrupt flow" function this is getting the job done nicely and encapsulates very complex logic with just a few nodes.
from godot-behavior-tree.
Hello, weighing in on this quite late - just here to say that I've had some success implementing this locally without too much refactoring, and I wanted to share my approach in case it is useful toward the official implementation (or to others finding this thread).
In bt_node.gd (unrelated sections elided):
signal completed(result)
const ABORTED = -1;
func abort():
fail()
complete(ABORTED)
func complete(value):
if running():
return
emit_signal("completed", value)
func tick(agent: Node, blackboard: Blackboard) -> bool:
# .... etc ...
if result is GDScriptFunctionState:
assert(running(), "BTNode execution was suspended but it's not running. Did you succeed() or fail() before yield?")
result.connect("completed", self, "complete")
result = yield(self, "completed")
if result is int and result == ABORTED:
return
and then in BehaviourTree:
# halt the behaviour tree
func interrupt() -> void:
bt_root.propagate_call("abort")
# halt the behaviour tree and restart it
# (useful for scenarios where an agent is surprised, eg taking damage, enemy arrives in range etc)
func hard_restart() -> void:
interrupt()
is_active = true
start()
The central change there is that the yield
inside tick
can now be terminated early by calling complete
on the node, rather than always having to wait for the underlying function call to finish. This allows for mechanisms that short circuit the node into a success or failure state as well as aborting it.
Of course there are some downsides to this approach - the function that the node was waiting on will still continue its execution uninterrupted, which might have strange side effects. This won't come up if nodes are designed to only do one thing (like, a node whose job is to wait and then execute a side effect should probably be split up into a waiter and an executor node) but perhaps this is too big of a tripping hazard to include without further safeguards. I also don't know how performant it is; my project only includes a handful of actors so it might have additional problems when dozens/hundreds of agents are in the scene.
Thanks @GabrieleTorini for the great module - it's so useful and extensible, it's been a great help to my hobby projects. I hope this is useful to you!
from godot-behavior-tree.
Thanks! This is definitely a great addition.
Would you like to make a PR for this? I'll try to see if it works with the sample project.
(I'm not a geet (git geek) so the whole process of the PR is probably gonna be clunky)
I'm glad you're happy with the plugin. It was a big experiment, and thinking back I think it could be done in an entirely different way, but as long as it's stable and gets you to make your AI, I'm satisfied!
from godot-behavior-tree.
Hello, weighing in on this quite late - just here to say that I've had some success implementing this locally without too much refactoring, and I wanted to share my approach in case it is useful toward the official implementation (or to others finding this thread).
In bt_node.gd (unrelated sections elided):
signal completed(result) const ABORTED = -1; func abort(): fail() complete(ABORTED) func complete(value): if running(): return emit_signal("completed", value) func tick(agent: Node, blackboard: Blackboard) -> bool: # .... etc ... if result is GDScriptFunctionState: assert(running(), "BTNode execution was suspended but it's not running. Did you succeed() or fail() before yield?") result.connect("completed", self, "complete") result = yield(self, "completed") if result is int and result == ABORTED: returnand then in BehaviourTree:
# halt the behaviour tree func interrupt() -> void: bt_root.propagate_call("abort") # halt the behaviour tree and restart it # (useful for scenarios where an agent is surprised, eg taking damage, enemy arrives in range etc) func hard_restart() -> void: interrupt() is_active = true start()The central change there is that the
yield
insidetick
can now be terminated early by callingcomplete
on the node, rather than always having to wait for the underlying function call to finish. This allows for mechanisms that short circuit the node into a success or failure state as well as aborting it.Of course there are some downsides to this approach - the function that the node was waiting on will still continue its execution uninterrupted, which might have strange side effects. This won't come up if nodes are designed to only do one thing (like, a node whose job is to wait and then execute a side effect should probably be split up into a waiter and an executor node) but perhaps this is too big of a tripping hazard to include without further safeguards. I also don't know how performant it is; my project only includes a handful of actors so it might have additional problems when dozens/hundreds of agents are in the scene.
Thanks @GabrieleTorini for the great module - it's so useful and extensible, it's been a great help to my hobby projects. I hope this is useful to you!
Hey there,
I'm using this piece of code for hard restarting the bt but it doesn't work for me. At least it doesn't work when the current leaf is under RepeatUntil. Have you checked it with RepeatUntil too ?
from godot-behavior-tree.
Related Issues (18)
- Function state of running BTNodes resumes on destroyed instances. HOT 3
- Visual editor HOT 3
- Add repeat frequency to bt_repeat and bt_repeat_until
- Make better looking icons
- Some Suggestions HOT 3
- Improve BBService structure to allow user control on the run() loop HOT 1
- The "abort_tree " signal may have the wrong target object HOT 7
- Invalid operands "String" and "Int" in operrate "==" HOT 4
- C++ Custom Native Module HOT 6
- ISSUSE occurs when using BTGuard Node!
- Memory optimization
- "Revert" should be "Invert"
- More flexible and friendly interface
- Seems to ignore tree.paused HOT 5
- Godot 4.0 branch HOT 1
- Plugin Root Path Doesn't Exist HOT 3
- Question about Few Things and Thank you for supporting this! <3 HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from godot-behavior-tree.