Compare commits

..

5 Commits

Author SHA1 Message Date
Serhii Snitsaruk 3a4caeb298
Merge pull request #198 from limbonaut/fix-btstate-overwriting-bb-vars
Don't overwrite exisiting blackboard variables in `BTState` upon initialization
2024-08-16 11:32:00 +02:00
Serhii Snitsaruk ee404c828a
Doc: Update using-blackboard.rst 2024-08-16 10:53:59 +02:00
Serhii Snitsaruk 43035839b1
Don't warn of mismatch between Object & NodePath 2024-08-16 00:44:37 +02:00
Serhii Snitsaruk cfacd57f15
Warn about type mismatch when populating blackboard 2024-08-15 23:41:39 +02:00
Serhii Snitsaruk 000f9c15d8
Fix BTState overwriting blackboard variables on init 2024-08-15 23:41:36 +02:00
5 changed files with 20 additions and 7 deletions

View File

@ -49,6 +49,7 @@ public:
Variant get_var(const StringName &p_name, const Variant &p_default = Variant(), bool p_complain = true) const; Variant get_var(const StringName &p_name, const Variant &p_default = Variant(), bool p_complain = true) const;
void set_var(const StringName &p_name, const Variant &p_value); void set_var(const StringName &p_name, const Variant &p_value);
bool has_var(const StringName &p_name) const; bool has_var(const StringName &p_name) const;
_FORCE_INLINE_ bool has_local_var(const StringName &p_name) const { return data.has(p_name); }
void erase_var(const StringName &p_name); void erase_var(const StringName &p_name);
void clear() { data.clear(); } void clear() { data.clear(); }
TypedArray<StringName> list_vars() const; TypedArray<StringName> list_vars() const;

View File

@ -416,7 +416,15 @@ void BlackboardPlan::populate_blackboard(const Ref<Blackboard> &p_blackboard, bo
ERR_FAIL_COND(p_node == nullptr && prefetch_nodepath_vars); ERR_FAIL_COND(p_node == nullptr && prefetch_nodepath_vars);
ERR_FAIL_COND(p_blackboard.is_null()); ERR_FAIL_COND(p_blackboard.is_null());
for (const Pair<StringName, BBVariable> &p : var_list) { for (const Pair<StringName, BBVariable> &p : var_list) {
if (p_blackboard->has_var(p.first) && !overwrite) { if (p_blackboard->has_local_var(p.first) && !overwrite) {
#ifdef DEBUG_ENABLED
Variant::Type existing_type = p_blackboard->get_var(p.first).get_type();
Variant::Type planned_type = p.second.get_type();
if (existing_type != planned_type && existing_type != Variant::NIL && planned_type != Variant::NIL && !(existing_type == Variant::OBJECT && planned_type == Variant::NODE_PATH)) {
WARN_PRINT(vformat("BlackboardPlan: Not overwriting %s as it already exists in the blackboard, but it has a different type than planned (%s vs %s). File: %s",
LimboUtility::get_singleton()->decorate_var(p.first), Variant::get_type_name(existing_type), Variant::get_type_name(planned_type), get_path()));
}
#endif
continue; continue;
} }
bool has_mapping = parent_scope_mapping.has(p.first); bool has_mapping = parent_scope_mapping.has(p.first);
@ -425,7 +433,7 @@ void BlackboardPlan::populate_blackboard(const Ref<Blackboard> &p_blackboard, bo
if (has_mapping) { if (has_mapping) {
StringName target_var = parent_scope_mapping[p.first]; StringName target_var = parent_scope_mapping[p.first];
if (target_var != StringName()) { if (target_var != StringName()) {
ERR_CONTINUE_MSG(p_blackboard->get_parent() == nullptr, vformat("BlackboardPlan: Cannot link variable $%s to parent scope because the parent scope is not set.", p.first)); ERR_CONTINUE_MSG(p_blackboard->get_parent() == nullptr, vformat("BlackboardPlan: Cannot link variable %s to parent scope because the parent scope is not set.", LimboUtility::get_singleton()->decorate_var(p.first)));
p_blackboard->link_var(p.first, p_blackboard->get_parent(), target_var); p_blackboard->link_var(p.first, p_blackboard->get_parent(), target_var);
} }
} }

View File

@ -183,6 +183,7 @@ void BTPlayer::_notification(int p_notification) {
blackboard = Ref<Blackboard>(memnew(Blackboard)); blackboard = Ref<Blackboard>(memnew(Blackboard));
} }
if (blackboard_plan.is_valid()) { if (blackboard_plan.is_valid()) {
// Don't overwrite existing blackboard values as they may be initialized from code.
blackboard_plan->populate_blackboard(blackboard, false, this); blackboard_plan->populate_blackboard(blackboard, false, this);
} }
if (behavior_tree.is_valid()) { if (behavior_tree.is_valid()) {

View File

@ -54,10 +54,12 @@ necessary for :ref:`BehaviorTree<class_BehaviorTree>` initialization.
To add, modify, or remove variables from the Blackboard Plan, follow these steps: To add, modify, or remove variables from the Blackboard Plan, follow these steps:
1. Load the behavior tree in the LimboAI editor. 1. Open the LimboAI editor and load the behavior tree you want to edit.
2. Click on the resource header to access :ref:`BehaviorTree<class_BehaviorTree>` data in the Inspector. 2. In the editor, click on the small button located inside the tab. This will open the :ref:`BlackboardPlan<class_BlackboardPlan>` in the Inspector.
3. In the Inspector, select the "Blackboard Plan" property and click the "Manage..." button. 3. In the Inspector, click the "Manage..." button to show the blackboard plan editor.
4. A popup window will appear, allowing you to edit behavior tree variables, reorder them, and modify property types and hints. 4. In the blackboard plan editor, you can add, remove, or reorder variables, and modify their data type and hint.
5. The hint provides additional information about the variable to the Inspector, such as minimum and maximum values for an integer variable. Learn more about `property hints in the official Godot documentation <https://docs.godotengine.org/en/stable/classes/class_%40globalscope.html#enum-globalscope-propertyhint>`_.
6. You can specify the default values of the variables directly in the Inspector.
Overriding variables in BTPlayer Overriding variables in BTPlayer
-------------------------------- --------------------------------

View File

@ -95,7 +95,8 @@ void LimboState::_initialize(Node *p_agent, const Ref<Blackboard> &p_blackboard)
blackboard = p_blackboard; blackboard = p_blackboard;
} }
if (blackboard_plan.is_valid() && !blackboard_plan->is_empty()) { if (blackboard_plan.is_valid() && !blackboard_plan->is_empty()) {
blackboard_plan->populate_blackboard(blackboard, true, this); // Don't overwrite existing blackboard values as they may be initialized from code.
blackboard_plan->populate_blackboard(blackboard, false, this);
} }
_setup(); _setup();