お世話になっております。
この間のCEDEC2018で講演されていた【UE4で多数のキャラクターを生かすためのテクニック】、【UE4アニメーションシステム総おさらい】を元にSkeletalMeshComponentからAnimationのFrameSkipを調整できるように対応してみました。
まず、概要から。
Engine.hにある、FAnimUpdateRateParametersがUpdateRate関連の調整パラメーターになります。
これは
FAnimUpdateRateParameters* GetUpdateRateParameters(USkinnedMeshComponent* SkinnedComponent)
内で実体が作成されており、
void USkinnedMeshComponent::OnRegister()、void USkinnedMeshComponent::RefreshUpdateRateParams()から呼び出されて割り当てが行われています。
BluePrintからこの割り当てられたインスタンスを使っても良いのですが、今回自分はインスタンス作成時に、調整したパラメーターを受け渡す形に致しました。
対応方法は以下になります。
//--------------Engine.h------//
最大スキップが4フレームを超えるとカラーが足りないので拡張。
必須な対応ではありません。
FColor GetUpdateRateDebugColor() const
{
if (OptimizeMode == TrailMode)
{
switch (UpdateRate)
{
case 1: return FColor::Red;
case 2: return FColor::Green;
case 3: return FColor::Blue;
//=====yuu_kajii@winter-crown-works.com=======//
#if 1
case 4: return FColor::Cyan;
case 5: return FColor::Magenta;
case 6: return FColor::Purple;
case 7: return FColor::Turquoise;
case 8: return FColor::Silver;
case 9: return FColor::Emerald;
#else
#endif
//======================================//
}
return FColor::Black;
}
else
{
if (bSkipUpdate)
{
return FColor::Yellow;
}
return FColor::Green;
}
}
//--------------------------------//
//-------SkinnedMeshComponent.h----//
デバッグカラーを増やしたのでコメントの調整。
FAnimUpdateRateParametersから欲しいパラメーターを移植。
// Update Rate
/** if TRUE, Owner will determine how often animation will be updated and evaluated. See AnimUpdateRateTick()
* This allows to skip frames for performance. (For example based on visibility and size on screen). /
UPROPERTY(EditAnywhere, AdvancedDisplay, BlueprintReadWrite, Category=Optimization)
uint8 bEnableUpdateRateOptimizations:1;
//============ yuu_kajii@winter-crown-works.com =========================//
#if 1
/* Enable on screen debugging of update rate optimization.
* Red = Skipping 0 frames, Green = skipping 1 frame, Blue = skipping 2 Cyan = skipping 3
Magenta = skipping 4 Purple = skipping 5 Turquoise = skipping 6 Silver = skipping 7
Emerald = skipping 8
frames, black = skipping more than 9 frames.
* @anonymous_user_5851a2121: turn this into a console command. /
UPROPERTY(EditAnywhere, AdvancedDisplay, BlueprintReadWrite, Category = Optimization)
uint8 bDisplayDebugUpdateRateOptimizations : 1;
#else
/* Enable on screen debugging of update rate optimization.
* Red = Skipping 0 frames, Green = skipping 1 frame, Blue = skipping 2 frames, black = skipping more than 2 frames.
* @anonymous_user_5851a2121: turn this into a console command. /
UPROPERTY(EditAnywhere, AdvancedDisplay, BlueprintReadWrite, Category = Optimization)
uint8 bDisplayDebugUpdateRateOptimizations : 1;
#endif
//=========================================================================//
//============ yuu_kajii@winter-crown-works.com =========================//
#if 1
/* Array of MaxDistanceFactor to use for AnimUpdateRate when mesh is visible (rendered).
* MaxDistanceFactor is size on screen, as used by LODs
* Example:
* BaseVisibleDistanceFactorThesholds.Add(0.4f)
* BaseVisibleDistanceFactorThesholds.Add(0.2f)
* means:
* 0 frame skip, MaxDistanceFactor > 0.4f
* 1 frame skip, MaxDistanceFactor > 0.2f
* 2 frame skip, MaxDistanceFactor > 0.0f
/
UPROPERTY(EditAnywhere, AdvancedDisplay, BlueprintReadOnly, Category = Optimization)
TArray BaseVisibleDistanceFactorThesholds;
/* When skipping a frame, should it be interpolated or frozen? /
UPROPERTY(EditAnywhere, AdvancedDisplay, BlueprintReadOnly, Category = Optimization)
uint8 bInterpolateSkippedFrames : 1;
/* Rate of animation evaluation when non rendered (off screen and dedicated servers).
* a value of 4 means evaluated 1 frame, then 3 frames skipped /
UPROPERTY(EditAnywhere, AdvancedDisplay, BlueprintReadOnly, Category = Optimization)
int32 BaseNonRenderedUpdateRate;
/* Max Evaluation Rate allowed for interpolation to be enabled. Beyond, interpolation will be turned off. /
UPROPERTY(EditAnywhere, AdvancedDisplay, BlueprintReadOnly, Category = Optimization)
int32 MaxEvalRateForInterpolation;
UPROPERTY(EditAnywhere, AdvancedDisplay, BlueprintReadOnly, Category = Optimization)
EUpdateRateShiftBucket ShiftBucket;
#endif
//============ ================================ =========================//
//------------------------------------------//
//-------SkinnedMeshComponent.cpp----//
ここで実体生成時にパラメーターを受け渡し。
FAnimUpdateRateParameters GetUpdateRateParameters(USkinnedMeshComponent* SkinnedComponent)
{
if (!SkinnedComponent)
{
return NULL;
}
UObject* TrackerIndex = GetMapIndexForComponent(SkinnedComponent);
FAnimUpdateRateParametersTracker** ExistingTrackerPtr = ActorToUpdateRateParams.Find(TrackerIndex);
if (!ExistingTrackerPtr)
{
ExistingTrackerPtr = &ActorToUpdateRateParams.Add(TrackerIndex);
(ExistingTrackerPtr) = new FAnimUpdateRateParametersTracker();
//============ yuu_kajii@winter-crown-works.com =========================//
#if 1
if (ExistingTrackerPtr != nullptr) {
FAnimUpdateRateParametersTracker pExistingTracker = ExistingTrackerPtr;
FAnimUpdateRateParameters pUpdateRateParams = &pExistingTracker-
>UpdateRateParameters;
pUpdateRateParams->BaseVisibleDistanceFactorThesholds = SkinnedComponent->BaseVisibleDistanceFactorThesholds;
pUpdateRateParams->bInterpolateSkippedFrames = SkinnedComponent->bInterpolateSkippedFrames;
pUpdateRateParams->BaseNonRenderedUpdateRate = SkinnedComponent->BaseNonRenderedUpdateRate;
pUpdateRateParams->MaxEvalRateForInterpolation = SkinnedComponent->MaxEvalRateForInterpolation;
pUpdateRateParams->ShiftBucket = SkinnedComponent->ShiftBucket;
}
#endif
//=========================================================================//
}
check(ExistingTrackerPtr);
FAnimUpdateRateParametersTracker* ExistingTracker = ExistingTrackerPtr;
check(ExistingTracker);
checkSlow(!ExistingTracker->RegisteredComponents.Contains(SkinnedComponent)); // We have already been registered? Something has gone very wrong!
ExistingTracker->RegisteredComponents.Add(SkinnedComponent);
FAnimUpdateRateParameters UpdateRateParams = &ExistingTracker->UpdateRateParameters;
SkinnedComponent->OnAnimUpdateRateParamsCreated.ExecuteIfBound(UpdateRateParams);
return UpdateRateParams;
}
//------------------//
//-----USkeletalMeshComponent.cpp-----------------//
初期値を入れておく。値はFAnimUpdateRateParametersに合わせました。
USkeletalMeshComponent::USkeletalMeshComponent(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
・
・
・
・
//============ yuu_kajii@winter-crown-works.com =========================//
#if 1
BaseVisibleDistanceFactorThesholds.Add(0.24f);
BaseVisibleDistanceFactorThesholds.Add(0.12f);
bInterpolateSkippedFrames = false;
BaseNonRenderedUpdateRate = 4;
MaxEvalRateForInterpolation = 4;
ShiftBucket = EUpdateRateShiftBucket::ShiftBucket0;
#endif
//============ ================================ =========================//
//---------------------------------------------------------------//
注意:
BaseVisibleDistanceFactorThesholdsの要素数を増やした場合、MaxEvalRateForInterpolation も増やさないとデフォルトでは4フレーム目のスキップから補間が切られるので注意。
BaseNonRenderedUpdateRate は描画されていないときのスキップフレームです。
以上です。これで4フレームスキップの補間あり等がSkeletalMeshComponentから設定が行えます。
参考になる方いらっしゃれば幸いです。
情報共有用なので、こちらで回答終了とさせていただきます。