Add events tracing feature to Animated Model for animation playback insights

This commit is contained in:
Wojtek Figat
2024-01-05 21:42:28 +01:00
parent b6337c748c
commit 6d58883454
5 changed files with 65 additions and 0 deletions

View File

@@ -56,6 +56,7 @@ void AnimGraphInstanceData::ClearState()
State.Resize(0);
NodesPose.Resize(0);
Slots.Clear();
TraceEvents.Clear();
}
void AnimGraphInstanceData::Invalidate()
@@ -238,6 +239,7 @@ void AnimGraphExecutor::Update(AnimGraphInstanceData& data, float dt)
}
for (auto& e : data.ActiveEvents)
e.Hit = false;
data.TraceEvents.Clear();
// Init empty nodes data
context.EmptyNodes.RootMotion = Transform::Identity;

View File

@@ -200,6 +200,21 @@ struct FLAXENGINE_API AnimGraphSlot
bool Reset = false;
};
/// <summary>
/// The animation graph state container for a single node playback trace (eg. animation sample info or state transition). Can be used by Anim Graph debugging or custom scripting.
/// </summary>
API_STRUCT() struct FLAXENGINE_API AnimGraphTraceEvent
{
DECLARE_SCRIPTING_TYPE_MINIMAL(AnimGraphTraceEvent);
// Contextual asset used. For example, sampled animation.
API_FIELD() Asset* Asset = nullptr;
// Generic value contextual to playback type (eg. animation sample position).
API_FIELD() float Value = 0;
// Identifier of the node in the graph.
API_FIELD() uint32 NodeId = 0;
};
/// <summary>
/// The animation graph instance data storage. Required to update the animation graph.
/// </summary>
@@ -358,6 +373,12 @@ public:
/// </summary>
void InvokeAnimEvents();
public:
// Anim Graph logic tracing feature that allows to collect insights of animations sampling and skeleton poses operations.
bool EnableTracing = false;
// Trace events collected when using EnableTracing option.
Array<AnimGraphTraceEvent> TraceEvents;
private:
struct OutgoingEvent
{

View File

@@ -219,6 +219,16 @@ void AnimGraphExecutor::ProcessAnimation(AnimGraphImpulse* nodes, AnimGraphNode*
const float animPos = GetAnimSamplePos(length, anim, pos, speed);
const float animPrevPos = GetAnimSamplePos(length, anim, prevPos, speed);
// Add to trace
auto& context = Context.Get();
if (context.Data->EnableTracing)
{
auto& trace = context.Data->TraceEvents.AddOne();
trace.Asset = anim;
trace.Value = animPos;
trace.NodeId = node->ID;
}
// Evaluate nested animations
bool hasNested = false;
if (anim->NestedAnims.Count() != 0)

View File

@@ -225,6 +225,17 @@ void AnimatedModel::SetMasterPoseModel(AnimatedModel* masterPose)
_masterPose->AnimationUpdated.Bind<AnimatedModel, &AnimatedModel::OnAnimationUpdated>(this);
}
const Array<AnimGraphTraceEvent>& AnimatedModel::GetTraceEvents() const
{
#if !BUILD_RELEASE
if (!GetEnableTracing())
{
LOG(Warning, "Accessing AnimatedModel.TraceEvents with tracing disabled.");
}
#endif
return GraphInstance.TraceEvents;
}
#define CHECK_ANIM_GRAPH_PARAM_ACCESS() \
if (!AnimationGraph) \
{ \

View File

@@ -259,6 +259,27 @@ public:
/// <param name="masterPose">The master pose actor to use.</param>
API_FUNCTION() void SetMasterPoseModel(AnimatedModel* masterPose);
/// <summary>
/// Enables extracting animation playback insights for debugging or custom scripting.
/// </summary>
API_PROPERTY(Attributes="HideInEditor, NoSerialize") bool GetEnableTracing() const
{
return GraphInstance.EnableTracing;
}
/// <summary>
/// Enables extracting animation playback insights for debugging or custom scripting.
/// </summary>
API_PROPERTY() void SetEnableTracing(bool value)
{
GraphInstance.EnableTracing = value;
}
/// <summary>
/// Gets the trace events from the last animation update. Valid only when EnableTracing is active.
/// </summary>
API_PROPERTY(Attributes="HideInEditor, NoSerialize") const Array<AnimGraphTraceEvent>& GetTraceEvents() const;
public:
/// <summary>
/// Gets the anim graph instance parameters collection.