Add Knowledge Conditional and Knowledge Values Conditional decorators to BT

This commit is contained in:
Wojtek Figat
2023-08-25 10:25:24 +02:00
parent cc7e93e2ee
commit b31f262214
6 changed files with 123 additions and 2 deletions

View File

@@ -68,7 +68,7 @@ bool AccessVariant(Variant& instance, const StringAnsiView& member, Variant& val
if (set)
mField->SetValue(instanceObject, MUtils::VariantToManagedArgPtr(value, mField->GetType(), failed));
else
value = MUtils::UnboxVariant(mField->GetValueBoxed(instanceObject));
value = MUtils::UnboxVariant(mField->GetValueBoxed(instanceObject));
return true;
}
else if (const auto mProperty = mClass->GetProperty(member.Get()))
@@ -76,7 +76,7 @@ bool AccessVariant(Variant& instance, const StringAnsiView& member, Variant& val
if (set)
mProperty->SetValue(instanceObject, MUtils::BoxVariant(value), nullptr);
else
value = MUtils::UnboxVariant(mProperty->GetValue(instanceObject, nullptr));
value = MUtils::UnboxVariant(mProperty->GetValue(instanceObject, nullptr));
return true;
}
}
@@ -173,3 +173,24 @@ bool BehaviorKnowledge::Set(const StringAnsiView& path, const Variant& value)
{
return AccessBehaviorKnowledge(this, path, const_cast<Variant&>(value), true);
}
bool BehaviorKnowledge::CompareValues(float a, float b, BehaviorValueComparison comparison)
{
switch (comparison)
{
case BehaviorValueComparison::Equal:
return Math::NearEqual(a, b);
case BehaviorValueComparison::NotEqual:
return Math::NotNearEqual(a, b);
case BehaviorValueComparison::Less:
return a < b;
case BehaviorValueComparison::LessEqual:
return a <= b;
case BehaviorValueComparison::Greater:
return a > b;
case BehaviorValueComparison::GreaterEqual:
return a >= b;
default:
return false;
}
}

View File

@@ -8,6 +8,7 @@
class Behavior;
class BehaviorTree;
enum class BehaviorValueComparison;
/// <summary>
/// Behavior logic component knowledge data container. Contains blackboard values, sensors data and goals storage for Behavior Tree execution.
@@ -69,4 +70,13 @@ API_CLASS() class FLAXENGINE_API BehaviorKnowledge : public ScriptingObject
/// <param name="value">Value to set.</param>
/// <returns>True if set value, otherwise false.</returns>
API_FUNCTION() bool Set(const StringAnsiView& path, const Variant& value);
/// <summary>
/// Compares two values and returns the comparision result.
/// </summary>
/// <param name="a">The left operand.</param>
/// <param name="b">The right operand.</param>
/// <param name="comparison">The comparison function.</param>
/// <returns>True if comparision passed, otherwise false.</returns>
API_FUNCTION() static bool CompareValues(float a, float b, BehaviorValueComparison comparison);
};

View File

@@ -435,3 +435,13 @@ void BehaviorTreeCooldownDecorator::PostUpdate(const BehaviorUpdateContext& cont
state->EndTime += context.Time;
}
}
bool BehaviorTreeKnowledgeConditionalDecorator::CanUpdate(const BehaviorUpdateContext& context)
{
return BehaviorKnowledge::CompareValues((float)ValueA.Get(context.Knowledge), ValueB, Comparison);
}
bool BehaviorTreeKnowledgeValuesConditionalDecorator::CanUpdate(const BehaviorUpdateContext& context)
{
return BehaviorKnowledge::CompareValues((float)ValueA.Get(context.Knowledge), (float)ValueB.Get(context.Knowledge), Comparison);
}

View File

@@ -292,3 +292,53 @@ public:
float EndTime;
};
};
/// <summary>
/// Checks certain knowledge value to conditionally enter the node.
/// </summary>
API_CLASS(Sealed) class FLAXENGINE_API BehaviorTreeKnowledgeConditionalDecorator : public BehaviorTreeDecorator
{
DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(BehaviorTreeKnowledgeConditionalDecorator, BehaviorTreeDecorator);
API_AUTO_SERIALIZATION();
// The first value from behavior's knowledge (blackboard, goal or sensor) to use for comparision.
API_FIELD(Attributes="EditorOrder(0)")
BehaviorKnowledgeSelectorAny ValueA;
// The second value to use for comparision.
API_FIELD(Attributes="EditorOrder(10)")
float ValueB = 0.0f;
// Values comparision mode.
API_FIELD(Attributes="EditorOrder(20)")
BehaviorValueComparison Comparison = BehaviorValueComparison::Equal;
public:
// [BehaviorTreeNode]
bool CanUpdate(const BehaviorUpdateContext& context) override;
};
/// <summary>
/// Checks certain knowledge value to conditionally enter the node.
/// </summary>
API_CLASS(Sealed) class FLAXENGINE_API BehaviorTreeKnowledgeValuesConditionalDecorator : public BehaviorTreeDecorator
{
DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(BehaviorTreeKnowledgeValuesConditionalDecorator, BehaviorTreeDecorator);
API_AUTO_SERIALIZATION();
// The first value from behavior's knowledge (blackboard, goal or sensor) to use for comparision.
API_FIELD(Attributes="EditorOrder(0)")
BehaviorKnowledgeSelectorAny ValueA;
// The second value from behavior's knowledge (blackboard, goal or sensor) to use for comparision.
API_FIELD(Attributes="EditorOrder(10)")
BehaviorKnowledgeSelectorAny ValueB;
// Values comparision mode.
API_FIELD(Attributes="EditorOrder(20)")
BehaviorValueComparison Comparison = BehaviorValueComparison::Equal;
public:
// [BehaviorTreeNode]
bool CanUpdate(const BehaviorUpdateContext& context) override;
};

View File

@@ -59,3 +59,22 @@ API_ENUM() enum class BehaviorUpdateResult
// Action failed.
Failed,
};
/// <summary>
/// Comparison function modes for behavior knowledge values.
/// </summary>
API_ENUM() enum class BehaviorValueComparison
{
// If A is equal to B, the comparison passes.
Equal,
// If A is not equal to B, the comparison passes.
NotEqual,
// If A is less than the B, the comparison passes.
Less,
// If A is less than or equal to the B, the comparison passes.
LessEqual,
// If A is greater than the B, the comparison passes.
Greater,
// If A is greater than or equal to the B, the comparison passes.
GreaterEqual,
};