Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updating BTSubTree.subtree at runtime #94

Open
onze opened this issue Apr 22, 2024 · 2 comments
Open

Updating BTSubTree.subtree at runtime #94

onze opened this issue Apr 22, 2024 · 2 comments

Comments

@onze
Copy link
Contributor

onze commented Apr 22, 2024

My tree contains a BTSubTree that I want to load dynamically. In order to do this, I leave the subtree field unset, and a sibling custom node does this:

var target_subtree: BTSubtree = find_btask(
	bt_player.get_tree_instance(), 
	my_subtree_task_name
) as BTSubtree
# assert target_subtree != null
target_subtree.subtree = null
var new_btree := ... # roughly load('res://...') as BehaviorTree
target_subtree.subtree = new_btree

In the editor, before this runs, I get the following error:

my_file.gd:95 @ <anonymous lambda>(): Subtree root task is not valid.
  <C++ Error>    Condition "!subtree->get_root_task().is_valid()" is true.
  <C++ Source>   limboai/bt/tasks/decorators/bt_subtree.cpp:33 @ initialize()

And when my code above runs, the task doesn't update properly.

As a workaround, I tried creating a dummy btree and assign it to the BTSubTree, so that the error isn't raised and the subtree can be replaced. It works until I try to set subtree to the new BehaviorTree, which doesn't raise an issue and doesn't update it.

Is this supported?

@onze onze changed the title BTSubTree prints an error for an unset tree before _enter BTSubTree sets itself in a failed state if started without subtree Apr 22, 2024
@onze onze changed the title BTSubTree sets itself in a failed state if started without subtree Updating BTSubTree.subtree at rutime Apr 22, 2024
@onze onze changed the title Updating BTSubTree.subtree at rutime Updating BTSubTree.subtree at runtime Apr 22, 2024
@limbonaut
Copy link
Owner

limbonaut commented Apr 22, 2024

There was a discussion some time ago: #58
It is currently not supported, as BTSubtree is designed to be a simple loader. However, you can do it dynamically, you just need to do it without BTSubtree, either by using a custom decorator, or by walking the tree and inserting your branch where you need it to be. Here's a simple example decorator (written from memory):

extends BTDecorator
## MyCustomBranch

func _setup() -> void:
    var bt: BehaviorTree = load("res://...")
    var my_branch: BTTask = bt.instantiate(agent, blackboard)
    add_child(my_branch)

func _tick(delta) -> Status:
    var child: BTTask = get_child(0)
    return child.execute(delta)

You may or may not want to isolate the blackboard scope for your subtree like this:

var new_scope := Blackboard.new()
new_scope.set_parent(blackboard)
var my_branch: BTTask = bt.instantiate(agent, new_scope)

If your branch utilizes blackboard plan system:

# Using new scope:
var new_scope: Blackboard = bt.blackboard_plan.create_blackboard(agent)
var my_branch: BTTask = bt.instantiate(agent, new_scope)

# Or not using new scope:
bt.blackboard_plan.populate_blackboard(blackboard, false, agent)
var my_branch: BTTask = bt.instantiate(agent, blackboard)

@onze
Copy link
Contributor Author

onze commented Apr 22, 2024

Makes sense, thanks for the quick answer. I opened a PR to add a quick mention to this in BTSubtree's doc itself. Feel free to dismiss it if you feel like it's too much detail.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants