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) if (set)
mField->SetValue(instanceObject, MUtils::VariantToManagedArgPtr(value, mField->GetType(), failed)); mField->SetValue(instanceObject, MUtils::VariantToManagedArgPtr(value, mField->GetType(), failed));
else else
value = MUtils::UnboxVariant(mField->GetValueBoxed(instanceObject)); value = MUtils::UnboxVariant(mField->GetValueBoxed(instanceObject));
return true; return true;
} }
else if (const auto mProperty = mClass->GetProperty(member.Get())) else if (const auto mProperty = mClass->GetProperty(member.Get()))
@@ -76,7 +76,7 @@ bool AccessVariant(Variant& instance, const StringAnsiView& member, Variant& val
if (set) if (set)
mProperty->SetValue(instanceObject, MUtils::BoxVariant(value), nullptr); mProperty->SetValue(instanceObject, MUtils::BoxVariant(value), nullptr);
else else
value = MUtils::UnboxVariant(mProperty->GetValue(instanceObject, nullptr)); value = MUtils::UnboxVariant(mProperty->GetValue(instanceObject, nullptr));
return true; return true;
} }
} }
@@ -173,3 +173,24 @@ bool BehaviorKnowledge::Set(const StringAnsiView& path, const Variant& value)
{ {
return AccessBehaviorKnowledge(this, path, const_cast<Variant&>(value), true); 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 Behavior;
class BehaviorTree; class BehaviorTree;
enum class BehaviorValueComparison;
/// <summary> /// <summary>
/// Behavior logic component knowledge data container. Contains blackboard values, sensors data and goals storage for Behavior Tree execution. /// 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> /// <param name="value">Value to set.</param>
/// <returns>True if set value, otherwise false.</returns> /// <returns>True if set value, otherwise false.</returns>
API_FUNCTION() bool Set(const StringAnsiView& path, const Variant& value); 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; 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; 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. // Action failed.
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,
};

View File

@@ -1506,6 +1506,7 @@ Variant::operator float() const
case VariantType::Float3: case VariantType::Float3:
return AsFloat3().X; return AsFloat3().X;
case VariantType::Float4: case VariantType::Float4:
case VariantType::Color:
return AsFloat4().X; return AsFloat4().X;
case VariantType::Double2: case VariantType::Double2:
return (float)AsDouble2().X; return (float)AsDouble2().X;
@@ -1519,6 +1520,16 @@ Variant::operator float() const
return (float)AsInt3().X; return (float)AsInt3().X;
case VariantType::Int4: case VariantType::Int4:
return (float)AsInt4().X; return (float)AsInt4().X;
case VariantType::Pointer:
return AsPointer ? 1.0f : 0.0f;
case VariantType::Object:
return AsObject ? 1.0f : 0.0f;
case VariantType::Asset:
return AsAsset ? 1.0f : 0.0f;
case VariantType::Blob:
return AsBlob.Length > 0 ? 1.0f : 0.0f;
case VariantType::ManagedObject:
return MANAGED_GC_HANDLE ? 1.0f : 0.0f;
default: default:
return 0; return 0;
} }