GithubHelp home page GithubHelp logo

kagenash1 / godot-behavior-tree Goto Github PK

View Code? Open in Web Editor NEW
190.0 11.0 24.0 266 KB

A GDScript implementation of a behavior tree for AI, built through Godot nodes.

License: Other

GDScript 100.00%
godot ai artificial-intelligence game-development behavior-tree

godot-behavior-tree's People

Contributors

kagenash1 avatar shargon-pendragon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

godot-behavior-tree's Issues

Make better looking icons

I literally made the icons on paint. Is there a generous artist willing to make some better looking and more artistically consistent icons?
They should be small (eg: 18x18) with a bit of a margin (eg: 2 pixels of marging and 16x16 icon)
The format should be .svg

Godot 4.0 branch

Hey there,

I started porting this plugin to Godot 4.0 on a branch in my own fork here. Some of the basic nodes like sequence and leaf nodes seem to work as expected. There are almost certainly bugs due to the rewrite of gdscript.

To save anyone interested from digging into the commits the current concerns in rough order of importance

  1. There is no more GDScriptFunctionState
  2. State variable of BTNode is not longer setget. Leaving it as a setget makes any behavior tree crash at runtime.
  3. Cannot have a signal and function named tick in BTNode.
  4. Ongoing bug with onready with new gdscript breaks some decorator nodes. They have been removed from the plugin for now.

ISSUSE occurs when using BTGuard Node!

I am new to the behavior tree,still learning .
today I create a test project and try build one simple behavior tree. looks like thi
捕获
s:
I use a parallel node as root, and first child of root is response to scan the target, measure the distance between. and CheckFound is also the lock and unlock object of BTGuard node (true->unlock,false->lock)
second child of root is the BTGuard node,which I want to be unlock when target is found.

when I run the test ,this error appears:
"Invalid BTNodeState assignment. Can only set to success or failure."

the debug result shows that when executing the tick() method of the Selector Node, its already running, so in the _tick() method of
BTGuard ,it get a result of false ,and child state is still running.

maybe I've misuse the BTGuard node because Im new to behavior tree ,but still want to know when and how to properly use BTGuard and do not run into problems!

The "abort_tree " signal may have the wrong target object

As you can see in the screenshot bellow, what you want to abort may be the "BehaviorTree" node, but actually in my case it can raise an error, because the real "owner" is "ai_test" node and it doesn't have any "abort( )" function. :)

image
image

Function state of running BTNodes resumes on destroyed instances.

A lot of BTNodes and BBServices suspend execution through yield() calls. This is good as it avoids running things at each frame and allows more control over the flow of the script. However, if we destroy an object, a lot of errors will be thrown because those function states are resumed after a script/class instance has been destroyed (as in the example below).

Screenshot 2021-03-09 005449

Plugin Root Path Doesn't Exist

I'd suggest using the standard setup of "addons/<plugin_name>" - IF this is intended to be an asset rather than a demo or proof of concept.

Also, the required directory root doesn't exist (see attached pic) and won't ever exist. (see note about actual dir names below)

godot_btree_bug

Actual dir names by download method:

  1. github: godot-behaviour-tree-master
  2. Godot Asset Library: godot-behavior-tree-3d8e1fc3d95ce7e5d3adafda9546fdf6f47a0a38 (dynamic, will continue to change)

Small issue(s), that can be easily fixed by the end user, but:

  1. Why make the install harder than necessary?
  2. If I see problems with the initial setup and bare minimum functionality, I lose trust in the whole project. I'm sure there are others who are the same.

Question about Few Things and Thank you for supporting this! <3

So, I have been looking into different behavior trees and everything to jumpstart. This is probably the best I have seen so far and loving the constant support. I tried few behaviors with timer and it's pretty fun to see the flow right on the tree.
I will start with the questions:

  • Why did you opt for physics_frame and idle_frame approach than normal process and physics_process? Not going to lie, I am loving this and did learn a new thing. Are they even different from godot's own built in functions (idle = process, physics = physics_process)?

  • I created this custom patrol behaviour (it's barebones right now) but I keep getting assertion failed because of "not running()". The code is below.

go_to_position.gd

extends BTLeaf

func _tick(agent: Node, blackboard: Blackboard) -> bool:
	var ag = agent as Agent
	ag.move_towards_position(Vector2(85, 190), blackboard.get_data('delta'))
	if ag.global_position.distance_to(Vector2(85, 190)) <= 50:
		return succeed()
	return running()

agent.gd

extends KinematicBody2D
class_name Agent

export (NodePath) var blackboard_path
export (float) var speed

onready var blackboard = get_node_or_null(blackboard_path)
onready var sprite: Sprite = $Sprite

var velocity: Vector2

func _ready():
	blackboard.set_data('position', $Node/Position2D.global_position)

func _physics_process(delta):
	blackboard.set_data('delta', delta)

func move_towards_position(target_position: Vector2, delta: float):
	print(target_position)
	var difference = (target_position - position).normalized()
	velocity = move_and_slide(difference * speed, Vector2.UP)
	velocity.normalized()

I am pretty sure it's my mistake, if so.. I would love to know fix and few pointers based on the script. You have been massive help to my workflow, I would love to continue using this.

Improve BBService structure to allow user control on the run() loop

Services are supposed to run at the specified frequency. So the run() function calls the virtual _run() at each loop iteration and handles the execution frequency so that the user only needs to worry about the custom logic.

However, if the user wants to preallocate memory outside of the loop (like storing immutable data in a variable to avoid repeatedly creating and destroying references for something that doesn't ever change), this is not possible as the virtual function _run() is called at each loop iteration.

Improvements to the structure are needed to allow memory optimization while maintaining the desired execution flow of the service, with the run() loop iterating at the specified frequency and the user only overriding the virtual _run().

Screenshot 2021-03-09 010621

Seems to ignore tree.paused

Hi, I have been using your plugin with great success so far, so thanks for your work!

However I have now implemented a pause menu of sorts and the behavior tree seems to be still executing - basically even though everything else is frozen, my agents keep moving forward but do nothing else.

I don't know if you're still working on this but if you do this might be something to look into.

Edit: I did modify the script a little and that seems to do it. Basically only tick the child if the tree is unpaused.

func run():

	var blackboard: Blackboard = get_node(_blackboard)
	var bt_root: BTNode = get_child(0)
	var agent: Node = get_node(_agent)
	var tick_result
	
	while is_active:
		if !get_tree().paused:		
			tick_result = bt_root.tick(agent, blackboard)
		
			if tick_result is GDScriptFunctionState:
				tick_result = yield(tick_result, "completed")
		
		if sync_mode == "idle":
			yield(get_tree(), "idle_frame") 
		else:
			yield(get_tree(), "physics_frame")

Interrupting flow

This may already be covered, but the current implementation doesn't provide any obvious solution on how to do this. If you an AI agent perform a sequence using things like wait timers or other yields, there doesn't seem to be any way to get them to re-evaluate from a higher level node based on external stimuli. An example might be an AI who simply wanders around, but if they get attacked, you would want their wander sequence interrupted and may instead go into an attack sequence.

C++ Custom Native Module

I'm amazed by this plugin, do you have interest in creating a secondary branch with a native custom module implementation?

It requires re-compilation of the editor to be used, but would add nice features like the classes documentation in Search Help and better runtime performance.

Visual editor

Thanks for this great addon!

  • 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 addon‘s code.

  • 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.

  • But still, an external editor is not so handy as desired. I suggest developing a behavior tree editor, which makes use of Godot's internal editor . That may make AI editing and debugging a lot easier.

  • I am look forward to some progress on this. LOL

Here are some screenshots of my external editor. I am grad to share this tool if someone needs.

image

image

image

image

image

image

Originally posted by @MadFlyFish in #8

Add repeat frequency to bt_repeat and bt_repeat_until

The repeater nodes currently wait for running actions, but do not wait for the next frame. This can easily result in unwanted behavior, for example when repeating move_and_slide(), as it will execute it in a loop and will result in the agent suddenly snapping.

Can easily be fixed by waiting for a given time at the end of the loop.

Some Suggestions

Ok, I've found some things that could be changed to improve optimization max as possible:

Behavior_tree.gd

  • The debug option,( seems to make no difference here?):
    image

  • Remove the Red box, and add the green one:

image

Other

I looked at other scripts, there's nothing more I can find to improve

About a Manager

What you can do is a manager script (tool) that check for the "BehaviorTree" node in the current edited scene, and check at every tree_changed event if the childs are correct (number of childs, expected child node, and so on)

Debug Stuff

I think that, instead of checking if (debug) everytime, you can make debug functions to be called instead of the main ones e.g:
run() and run_debug(). Or new classes like Selector and SelectorDebug, there are lots of ways.

Final Toughts

  • My english is not one of the bests, but I think I've passed the essence of things here
  • This ideas are not mandatory, but just some toughts that can evolve...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.