概要
このコードはStatsコマンドで出力される内容を個別に指定してログに出力します。UAutomationBlueprintFunctionLibrary で定義された、GetStatIncAverage
や GetStatIncMax
といった関数を利用することもできますが、これらで取得できるは項目は一部に限定されます。このサンプルでは Counters Aggregates の項目も含める内容となります。
動作例
入力
確認したいstatsのグループおよび項目をBlueprintから指定します。コンソールコマンドからstatsを実行(この場合stat netを実行)して、該当ノードをアプリケーションから呼び出します。
出力
LogTemp: Name = STAT_OutBunches, IncAvg = 26.07, IncMin = 2.00, IncMaxMs = 40.00
サンプル例
StatsRender2.cppを元に以下のような例が挙げられます。これを少し変更することで異なる型やExcMaxなどの値も取得できます。
MyBlueprintFunctionLibrary.h
#include "MyBlueprintFunctionLibrary.h"
void UMyBlueprintFunctionLibrary::OutputStatsValue(const FName GroupName, const FName StatName)
{
if (FGameThreadStatsData* StatsData = FLatestGameThreadStatsData::Get().Latest)
{
if (!StatsData)
{
return;
}
for (int32 GroupIndex = 0; GroupIndex < StatsData->ActiveStatGroups.Num(); ++GroupIndex)
{
const FActiveStatGroupInfo& StatGroup = StatsData->ActiveStatGroups[GroupIndex];
if (!StatsData->GroupNames[GroupIndex].IsEqual(GroupName))
{
continue;
}
const bool bBudget = StatGroup.ThreadBudgetMap.Num() > 0;
const int32 NumThreadsBreakdown = bBudget ? StatGroup.FlatAggregateThreadBreakdown.Num() : 1;
TArray<FName> ThreadNames;
StatGroup.FlatAggregateThreadBreakdown.GetKeys(ThreadNames);
for (int32 ThreadBreakdownIdx = 0; ThreadBreakdownIdx < NumThreadsBreakdown; ++ThreadBreakdownIdx)
{
FName ThreadName;
if (bBudget)
{
ThreadName = ThreadNames[ThreadBreakdownIdx];
}
const bool bHasFlat = !!StatGroup.FlatAggregate.Num();
if (bHasFlat)
{
// Flat Aggregates
TArray<FComplexStatMessage> Aggregates = bBudget ? StatGroup.FlatAggregateThreadBreakdown[ThreadName] : StatGroup.FlatAggregate;
for (const auto& ComplexStat : Aggregates)
{
if (ComplexStat.NameAndInfo.GetShortName().IsEqual(StatName))
{
FString IncAveStr = GetStatValueString(ComplexStat, EComplexStatField::IncAve);
FString IncMinStr = GetStatValueString(ComplexStat, EComplexStatField::IncMin);
FString IncMaxStr = GetStatValueString(ComplexStat, EComplexStatField::IncMax);
FString ComplaxStatName = ComplexStat.NameAndInfo.GetShortName().ToString();
UE_LOG(LogTemp, Log, TEXT("Name = %s, IncAvg = %s, IncMin = %s, IncMaxMs = %s"), *ComplaxStatName, *IncAveStr, *IncMinStr, *IncMaxStr);
return;
}
}
}
}
// Counters Aggregates
if (StatGroup.CountersAggregate.Num())
{
const TArray<FComplexStatMessage> Aggregates = StatGroup.CountersAggregate;
for (const auto& ComplexStat : Aggregates)
{
if (ComplexStat.NameAndInfo.GetShortName().IsEqual(StatName))
{
FString IncAveStr = GetStatValueString(ComplexStat, EComplexStatField::IncAve);
FString IncMinStr = GetStatValueString(ComplexStat, EComplexStatField::IncMin);
FString IncMaxStr = GetStatValueString(ComplexStat, EComplexStatField::IncMax);
FString ComplaxStatName = ComplexStat.NameAndInfo.GetShortName().ToString();
UE_LOG(LogTemp, Log, TEXT("Name = %s, IncAvg = %s, IncMin = %s, IncMaxMs = %s"), *ComplaxStatName, *IncAveStr, *IncMinStr, *IncMaxStr);
return;
}
}
}
}
}
UE_LOG(LogTemp, Warning, TEXT("Not found stats name"));
}
FString UMyBlueprintFunctionLibrary::GetStatValueString(const FComplexStatMessage& ComplexStat, const EComplexStatField::Type Type)
{
FString StatsValueString = "";
if (ComplexStat.NameAndInfo.GetField<EStatDataType>() == EStatDataType::ST_double)
{
StatsValueString += FormatStatValueFloat(ComplexStat.GetValue_double(Type));
}
else if (ComplexStat.NameAndInfo.GetField<EStatDataType>() == EStatDataType::ST_int64)
{
StatsValueString += FormatStatValueInt64(ComplexStat.GetValue_int64(Type));
}
return StatsValueString;
}
FString UMyBlueprintFunctionLibrary::FormatStatValueFloat(const float Value)
{
const float Frac = FMath::Frac(Value);
const int32 Integer = FMath::FloorToInt(Value);
const FString IntString = FString::FormatAsNumber(Integer);
const FString FracString = FString::Printf(TEXT("%0.2f"), Frac);
const FString Result = FString::Printf(TEXT("%s.%s"), *IntString, *FracString.Mid(2));
return Result;
}
FString UMyBlueprintFunctionLibrary::FormatStatValueInt64(const int64 Value)
{
const FString IntString = FString::FormatAsNumber((int32)Value);
return IntString;
}