BTPlayer: Allow changing BT instance at runtime

This commit is contained in:
Serhii Snitsaruk 2024-08-04 12:36:44 +02:00
parent 0f82fa3d64
commit ee12a56e96
No known key found for this signature in database
GPG Key ID: A965EF8799FFEC2D
10 changed files with 127 additions and 25 deletions

View File

@ -127,6 +127,10 @@ void BTInstance::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_owner_node"), &BTInstance::get_owner_node);
ClassDB::bind_method(D_METHOD("get_last_status"), &BTInstance::get_last_status);
ClassDB::bind_method(D_METHOD("get_source_bt_path"), &BTInstance::get_source_bt_path);
ClassDB::bind_method(D_METHOD("get_agent"), &BTInstance::get_agent);
ClassDB::bind_method(D_METHOD("get_blackboard"), &BTInstance::get_blackboard);
ClassDB::bind_method(D_METHOD("is_instance_valid"), &BTInstance::is_instance_valid);
ClassDB::bind_method(D_METHOD("set_monitor_performance", "monitor"), &BTInstance::set_monitor_performance);
ClassDB::bind_method(D_METHOD("get_monitor_performance"), &BTInstance::get_monitor_performance);

View File

@ -41,8 +41,11 @@ public:
_FORCE_INLINE_ Ref<BTTask> get_root_task() const { return root_task; }
_FORCE_INLINE_ Node *get_owner_node() const { return owner_node_id ? Object::cast_to<Node>(OBJECT_DB_GET_INSTANCE(owner_node_id)) : nullptr; }
_FORCE_INLINE_ BT::Status get_last_status() const { return last_status; }
_FORCE_INLINE_ bool is_instance_valid() const { return root_task.is_valid(); }
_FORCE_INLINE_ String get_source_bt_path() const { return source_bt_path; }
_FORCE_INLINE_ Node *get_agent() const { return root_task.is_valid() ? root_task->get_agent() : nullptr; }
_FORCE_INLINE_ Ref<Blackboard> get_blackboard() const { return root_task.is_valid() ? root_task->get_blackboard() : Ref<Blackboard>(); }
_FORCE_INLINE_ bool is_instance_valid() const { return root_task.is_valid(); }
BT::Status update(double p_delta);

View File

@ -69,6 +69,18 @@ void BTPlayer::_update_blackboard_plan() {
blackboard_plan->set_base_plan(behavior_tree.is_valid() ? behavior_tree->get_blackboard_plan() : nullptr);
}
void BTPlayer::set_bt_instance(const Ref<BTInstance> &p_bt_instance) {
ERR_FAIL_COND_MSG(p_bt_instance.is_null(), "BTPlayer: Failed to set behavior tree instance - instance is null.");
ERR_FAIL_COND_MSG(!p_bt_instance->is_instance_valid(), "BTPlayer: Failed to set behavior tree instance - instance is not valid.");
bt_instance = p_bt_instance;
blackboard = p_bt_instance->get_blackboard();
agent_node = p_bt_instance->get_agent()->get_path();
blackboard_plan.unref();
behavior_tree.unref();
}
void BTPlayer::set_behavior_tree(const Ref<BehaviorTree> &p_tree) {
if (Engine::get_singleton()->is_editor_hint()) {
if (behavior_tree.is_valid() && behavior_tree->is_connected(LW_NAME(plan_changed), callable_mp(this, &BTPlayer::_update_blackboard_plan))) {
@ -217,6 +229,7 @@ void BTPlayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("restart"), &BTPlayer::restart);
ClassDB::bind_method(D_METHOD("get_bt_instance"), &BTPlayer::get_bt_instance);
ClassDB::bind_method(D_METHOD("set_bt_instance", "bt_instance"), &BTPlayer::set_bt_instance);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "behavior_tree", PROPERTY_HINT_RESOURCE_TYPE, "BehaviorTree"), "set_behavior_tree", "get_behavior_tree");
ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "agent_node"), "set_agent_node", "get_agent_node");

View File

@ -77,6 +77,7 @@ public:
void restart();
Ref<BTInstance> get_bt_instance() { return bt_instance; }
void set_bt_instance(const Ref<BTInstance> &p_bt_instance);
BTPlayer();
~BTPlayer();

View File

@ -174,7 +174,7 @@ Returns the root task of the BehaviorTree resource.
:ref:`BTInstance<class_BTInstance>` **instantiate**\ (\ agent\: ``Node``, blackboard\: :ref:`Blackboard<class_Blackboard>`, instance_owner\: ``Node``\ ) |const| :ref:`🔗<class_BehaviorTree_method_instantiate>`
Instantiates the behavior tree and returns :ref:`BTInstance<class_BTInstance>`. ``instance_owner`` should be the scene node that will own the behavior tree instance. This is typically a :ref:`BTPlayer<class_BTPlayer>`, :ref:`BTState<class_BTState>`, or a custom player node that controls the behavior tree execution.
Instantiates the behavior tree and returns :ref:`BTInstance<class_BTInstance>`. ``instance_owner`` should be the scene node that will own the behavior tree instance. This is typically a :ref:`BTPlayer<class_BTPlayer>`, :ref:`BTState<class_BTState>`, or a custom player node that controls the behavior tree execution. Make sure to pass a :ref:`Blackboard<class_Blackboard>` with values populated from :ref:`blackboard_plan<class_BehaviorTree_property_blackboard_plan>`. See also ``BlackboardPlan.populate_blackboard`` & ``BlackboardPlan.create_blackboard``.
.. rst-class:: classref-item-separator

View File

@ -41,21 +41,27 @@ Methods
.. table::
:widths: auto
+-------------------------------+-----------------------------------------------------------------------------------------+
+-------------------------------------+-----------------------------------------------------------------------------------------+
| ``Node`` | :ref:`get_agent<class_BTInstance_method_get_agent>`\ (\ ) |const| |
+-------------------------------------+-----------------------------------------------------------------------------------------+
| :ref:`Blackboard<class_Blackboard>` | :ref:`get_blackboard<class_BTInstance_method_get_blackboard>`\ (\ ) |const| |
+-------------------------------------+-----------------------------------------------------------------------------------------+
| :ref:`Status<enum_BT_Status>` | :ref:`get_last_status<class_BTInstance_method_get_last_status>`\ (\ ) |const| |
+-------------------------------+-----------------------------------------------------------------------------------------+
+-------------------------------------+-----------------------------------------------------------------------------------------+
| ``Node`` | :ref:`get_owner_node<class_BTInstance_method_get_owner_node>`\ (\ ) |const| |
+-------------------------------+-----------------------------------------------------------------------------------------+
+-------------------------------------+-----------------------------------------------------------------------------------------+
| :ref:`BTTask<class_BTTask>` | :ref:`get_root_task<class_BTInstance_method_get_root_task>`\ (\ ) |const| |
+-------------------------------+-----------------------------------------------------------------------------------------+
+-------------------------------------+-----------------------------------------------------------------------------------------+
| ``String`` | :ref:`get_source_bt_path<class_BTInstance_method_get_source_bt_path>`\ (\ ) |const| |
+-------------------------------+-----------------------------------------------------------------------------------------+
+-------------------------------------+-----------------------------------------------------------------------------------------+
| ``bool`` | :ref:`is_instance_valid<class_BTInstance_method_is_instance_valid>`\ (\ ) |const| |
+-------------------------------------+-----------------------------------------------------------------------------------------+
| |void| | :ref:`register_with_debugger<class_BTInstance_method_register_with_debugger>`\ (\ ) |
+-------------------------------+-----------------------------------------------------------------------------------------+
+-------------------------------------+-----------------------------------------------------------------------------------------+
| |void| | :ref:`unregister_with_debugger<class_BTInstance_method_unregister_with_debugger>`\ (\ ) |
+-------------------------------+-----------------------------------------------------------------------------------------+
+-------------------------------------+-----------------------------------------------------------------------------------------+
| :ref:`Status<enum_BT_Status>` | :ref:`update<class_BTInstance_method_update>`\ (\ delta\: ``float``\ ) |
+-------------------------------+-----------------------------------------------------------------------------------------+
+-------------------------------------+-----------------------------------------------------------------------------------------+
.. rst-class:: classref-section-separator
@ -117,6 +123,30 @@ If ``true``, adds a performance monitor for this instance to "Debugger->Monitors
Method Descriptions
-------------------
.. _class_BTInstance_method_get_agent:
.. rst-class:: classref-method
``Node`` **get_agent**\ (\ ) |const| :ref:`🔗<class_BTInstance_method_get_agent>`
Returns the agent of the behavior tree instance.
.. rst-class:: classref-item-separator
----
.. _class_BTInstance_method_get_blackboard:
.. rst-class:: classref-method
:ref:`Blackboard<class_Blackboard>` **get_blackboard**\ (\ ) |const| :ref:`🔗<class_BTInstance_method_get_blackboard>`
Returns the blackboard of the behavior tree instance.
.. rst-class:: classref-item-separator
----
.. _class_BTInstance_method_get_last_status:
.. rst-class:: classref-method
@ -165,6 +195,18 @@ Returns the file path to the behavior tree resource that was used to create this
----
.. _class_BTInstance_method_is_instance_valid:
.. rst-class:: classref-method
``bool`` **is_instance_valid**\ (\ ) |const| :ref:`🔗<class_BTInstance_method_is_instance_valid>`
Returns ``true`` if the behavior tree instance is properly initialized and can be used.
.. rst-class:: classref-item-separator
----
.. _class_BTInstance_method_register_with_debugger:
.. rst-class:: classref-method

View File

@ -55,13 +55,15 @@ Methods
.. table::
:widths: auto
+-------------------------------------+----------------------------------------------------------------------+
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------+
| :ref:`BTInstance<class_BTInstance>` | :ref:`get_bt_instance<class_BTPlayer_method_get_bt_instance>`\ (\ ) |
+-------------------------------------+----------------------------------------------------------------------+
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------+
| |void| | :ref:`restart<class_BTPlayer_method_restart>`\ (\ ) |
+-------------------------------------+----------------------------------------------------------------------+
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------+
| |void| | :ref:`set_bt_instance<class_BTPlayer_method_set_bt_instance>`\ (\ bt_instance\: :ref:`BTInstance<class_BTInstance>`\ ) |
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------+
| |void| | :ref:`update<class_BTPlayer_method_update>`\ (\ delta\: ``float``\ ) |
+-------------------------------------+----------------------------------------------------------------------+
+-------------------------------------+------------------------------------------------------------------------------------------------------------------------+
.. rst-class:: classref-section-separator
@ -289,6 +291,18 @@ Resets the behavior tree's execution. Each running task will be aborted and the
----
.. _class_BTPlayer_method_set_bt_instance:
.. rst-class:: classref-method
|void| **set_bt_instance**\ (\ bt_instance\: :ref:`BTInstance<class_BTInstance>`\ ) :ref:`🔗<class_BTPlayer_method_set_bt_instance>`
Sets the :ref:`BTInstance<class_BTInstance>` to play. This method is useful when you want to switch to a different behavior tree instance at runtime. See also :ref:`BehaviorTree.instantiate<class_BehaviorTree_property_instantiate>`.
.. rst-class:: classref-item-separator
----
.. _class_BTPlayer_method_update:
.. rst-class:: classref-method

View File

@ -9,6 +9,18 @@
<tutorials>
</tutorials>
<methods>
<method name="get_agent" qualifiers="const">
<return type="Node" />
<description>
Returns the agent of the behavior tree instance.
</description>
</method>
<method name="get_blackboard" qualifiers="const">
<return type="Blackboard" />
<description>
Returns the blackboard of the behavior tree instance.
</description>
</method>
<method name="get_last_status" qualifiers="const">
<return type="int" enum="BT.Status" />
<description>
@ -33,6 +45,12 @@
Returns the file path to the behavior tree resource that was used to create this instance.
</description>
</method>
<method name="is_instance_valid" qualifiers="const">
<return type="bool" />
<description>
Returns [code]true[/code] if the behavior tree instance is properly initialized and can be used.
</description>
</method>
<method name="register_with_debugger">
<return type="void" />
<description>

View File

@ -22,6 +22,13 @@
Resets the behavior tree's execution. Each running task will be aborted and the next tree execution will start anew. This method does not reset [Blackboard].
</description>
</method>
<method name="set_bt_instance">
<return type="void" />
<param index="0" name="bt_instance" type="BTInstance" />
<description>
Sets the [BTInstance] to play. This method is useful when you want to switch to a different behavior tree instance at runtime. See also [member BehaviorTree.instantiate].
</description>
</method>
<method name="update">
<return type="void" />
<param index="0" name="delta" type="float" />

View File

@ -40,7 +40,7 @@
<param index="1" name="blackboard" type="Blackboard" />
<param index="2" name="instance_owner" type="Node" />
<description>
Instantiates the behavior tree and returns [BTInstance]. [param instance_owner] should be the scene node that will own the behavior tree instance. This is typically a [BTPlayer], [BTState], or a custom player node that controls the behavior tree execution.
Instantiates the behavior tree and returns [BTInstance]. [param instance_owner] should be the scene node that will own the behavior tree instance. This is typically a [BTPlayer], [BTState], or a custom player node that controls the behavior tree execution. Make sure to pass a [Blackboard] with values populated from [member blackboard_plan]. See also [BlackboardPlan.populate_blackboard] &amp; [BlackboardPlan.create_blackboard].
</description>
</method>
<method name="set_root_task">