Animation Budget Allocator (または Anim Budgeter) システムは、スケルタル メッシュ コンポーネントのティックを動的にスロットリングすることで実行されるアニメーション データにかかる時間を制限します。 そのシステムを使用すると、最小限のシステム オーバーヘッドで知覚できるアニメーション品質を最大にしながら、固定の CPU バジェットを (超えないようにして) 実行できます。
システムはプラットフォームごとに (ゲームスレッドで実行する作業のミリ秒 (ms) で) 固定の割り当てバジェット時間を決定し、必要な作業がすべて実行できるか、または削減する必要があるかどうかを計算します。 作業を減らす必要がある場合は、重要度に応じて複数の領域を対象に負荷を動的に調整して、固定 (ゲームスレッド) 割り当てバジェット内に収まるようにします。 その領域は次のとおりです。
-
ティックを停止し、マスター ポーズ コンポーネント を使用する。
-
より低いレートで更新を実行する。
-
更新間の補間をするかしないか。
Anim Budgeter を有効にする
Animation Budget Allocator を使うには、まず [Plugins] メニューから有効にする必要があります。
-
[Edit (編集)] > [Plugins] オプションから [Plugins] メニューを開きます。
-
[Programming] の下で、Animation Budget Allocator プラグインを有効にしてエディタを再起動します。
Anim Budgeter を使用する
Anim Budgeter を使用するには、「`」(Backtick キー) もしくは日本語環境では「@」を押して次のコンソール コマンドを入力します。
-
有効にするには「a.Budget.Enabled 1」
-
無効にするには「a.Budget.Enabled 0」
プラグインを有効にすると、Anim Budgeter が自動的に有効となります。
Enable Animation Budget ブループリント ノードを使用して Anim Budgeter の有効と無効を切り替えることも可能です。
現時点では、ブループリントに公開されている機能はこれだけです。それ以外のシステムはコンソール変数と C++ API コールでアクセスします。
デバッグ表示を有効にするには以下の通り実行します。
デバッグ情報の表示機能は現在 GitHUb のマスター ブランチのみで利用できます。この機能は 4.23 でさらに広く使用可能になります。
-
デバッグ表示を有効にするには「a.Budget.Debug.Enabled 1」
-
デバッグ表示を無効にするには「a.Budget.Debug.Enabled 0」
有効にすると、実行時にビューポート内にグラフが表示されます。
グラフは次のもので構成されています。
-
ミリ秒単位の時間は 1 カーネル約 20 フレームとスムーズになり、傾向や 1 ティックあたりの時間がわかりやすくなりました。
-
合計時間
-
Anim Budget (点線)
-
パフォーマンス (実線)
パフォーマンスは、実行する必要がある作業量によって異なります。 下記、点線は Anim Budget で実線はパフォーマンスです。 1 人のキャラクター (プレイヤー) がティックしているので、現在は割り当てバジェットの範囲内です。
以下では、キャラクター数を 10 に増やすと、パフォーマンスにスパイクが (ノイズ線) が現れるようになり、それに対する影響がわかります。 パフォーマンスには 2 本の線があります。灰色の線は実際のシステム パフォーマンスで、少しノイズが多く、システムの負荷によって変動します。 滑らかな白い線は、実際のシステム パフォーマンスをより正確に示しています。
以下の最後の例では、キャラクター数を 100 以上に増やしていることから、パフォーマンスが割り当てバジェット (点線) 周辺で推移していることがわかります。
これはアニメーション専用で、アニメーションがティックされる頻度を表します。
Anim Budgeter は、システムが行っている処理の全体量を割り当てバジェット内に収めるようにし、システムが生み出すことができる品質の最大化を試みます。 最も近くて重要なメッシュを可能な限り最高のフレームレートで実行しようとし、重要でないものや遠くにあるメッシュのフレームレートを低くします。 これは、実行する必要がある作業の総量が割り当てを埋める間にすべて行われます。
各スケルタル メッシュには、デバッグ データが表示されます。
数字はメッシュが更新されているレートを示します。 値が「1」の場合は、更新中であり、すべてのフレームでティックすることを意味します。 値が「5」の場合は、5 フレームごとに更新を行いティックすることを意味します。
一例として、Fortnite では、キャラクターはいくつかのスケルタル メッシュ (頭、ボディ、バックパックなど) で構成されていて、それらはすべて所定の時間と場所でティックします。 Anim Budgeter を実行すると、数値で表されるメッシュの更新頻度に加えて、 Lo、Hi、I のテキストが使用されていることがわかります。 これはメッシュがどのようにティックされるかを表します。
-
Hi (または高詳細度) - スケルタル メッシュ コンポーネントで、より高負荷なロジックを実行していることを意味します。
-
Lo (または低詳細度) - 高負荷なロジック (余分なキャラクターのパーツやさらに高負荷なタスクなど、距離がある時にスキップ可能なもの) が実行されていないことを意味します。
-
I (または補間) - スケルタル メッシュがフレーム間を補間していることを意味します。
以下の例は、必要なアニメーション作業量に基づいて Anim Budgeter の更新と優先順位がどのようにシフトされるかを示しています。
Anim Budgeter C++ API
下記のエンジンのインストール フォルダ内にある Anim Budgeter の C++ ファイルにアクセスできます。
- Engine\Plugins\Runtime\AnimationBudgetAllocator\Source\AnimationBudgetAllocator\Public\
以下は IAnimationBudgetAllocator.h: です。
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#pragma once
class USkeletalMeshComponentBudgeted;
class UWorld;
struct FAnimationBudgetAllocatorParameters;
/**
* 指定された割り当てバジェットを維持するためにスケルタル メッシュ コンポーネントのティック レートを動的に管理します。
*/
class IAnimationBudgetAllocator
{
public:
/** 指定されたワールドの割り当てバジェットを取得します */
static ANIMATIONBUDGETALLOCATOR_API IAnimationBudgetAllocator* Get(UWorld* InWorld);
/**
* コンポーネントを割り当てシステムに登録します。コンポーネントがすでに登録されている場合、この関数は何もしません。
* この関数が呼ばれると次のようになります。
* - デフォルトのティック関数の無効
* - URO の無効
* - 並列アニメーション タスクの割り当てシステムへの転送
*/
virtual void RegisterComponent(USkeletalMeshComponentBudgeted* InComponent) = 0;
/**
* 割り当てシステムからのコンポーネントの登録解除。 コンポーネントが登録されていない場合、この関数は何もしません。
* この関数が呼ばれると次のようになります。
* - デフォルトのティック機能の再有効化
* - URO の再有効化
* - 並列アニメーション タスクの内部関数への転送
*/
virtual void UnregisterComponent(USkeletalMeshComponentBudgeted* InComponent) = 0;
/**
* このコンポーネントの重要度と前提条件を更新します。
* 前提条件が外部から変更されている可能性がある場合に呼び出す必要があります。
*/
virtual void UpdateComponentTickPrerequsites(USkeletalMeshComponentBudgeted* InComponent) = 0;
/**
* 指定されたコンポーネントに重要度と他のフラグを設定します。
* この情報は、コンポーネントのティック レートを動的に制御するために使用されます。
*/
virtual void SetComponentSignificance(USkeletalMeshComponentBudgeted* Component, float Significance, bool bNeverSkip = false, bool bTickEvenIfNotRendered = false, bool bAllowReducedWork = true, bool bForceInterpolate = false) = 0;
/** 指定されたコンポーネントをティックするかどうかを設定します。 バジェット割り当てが無効になっている場合、Component->SetComponentTickEnabled(bShouldTick) が呼び出されます。 */
virtual void SetComponentTickEnabled(USkeletalMeshComponentBudgeted* Component, bool bShouldTick) = 0;
/** 指定されたコンポーネントがティックするかどうかを設定します */
virtual bool IsComponentTickEnabled(USkeletalMeshComponentBudgeted* Component) const = 0;
/** 指定されたコンポーネントがティックするように設定されているかどうかを取得します */
virtual void SetIsRunningReducedWork(USkeletalMeshComponentBudgeted* Component, bool bInReducedWork) = 0;
/** コンポーネントの作業量を削減したことを通知します */
virtual void SetGameThreadLastTickTimeMs(int32 InManagerHandle, float InGameThreadLastTickTimeMs) = 0;
/** 作業完了時間を設定します */
virtual void SetGameThreadLastCompletionTimeMs(int32 InManagerHandle, float InGameThreadLastCompletionTimeMs) = 0;
/** フレームごとにシステムをティックします */
virtual void Update(float DeltaSeconds) = 0;
/** このバジェット割り当てアロケータが有効かどうかを設定します */
virtual void SetEnabled(bool bInEnabled) = 0;
/** このバジェット割り当てアロケータが有効かどうかを取得します */
virtual bool GetEnabled() const = 0;
/** 異なるパラメータを設定します */
virtual void SetParameters(const FAnimationBudgetAllocatorParameters& InParameters) = 0;
};
追加のコンソール コマンド
Anim Budgeter のデバッグには、次のコンソール コマンドも使用できます。
プロパティ | 説明 |
---|---|
a.Budget.AlwaysTickFalloffAggression | 範囲 [0.1, 0.9]、デフォルト = 0.8 「常にティックされている」コンポーネントが、負荷時にフォールオフされるレートを制御します。 値が大きいと、割り当てられた時間割り当てを超過したときに、常にティックするコンポーネントの数が多くなります。 |
a.Budget.BudgetFactorBeforeAggressiveReducedWork | 範囲 > 1、デフォルト = 2.0 バジェット割り当て圧力がこの量を超えると、削減された作業がより迅速に適用されます。 |
a.Budget.BudgetFactorBeforeReduceWork | 範囲 > 1、デフォルト = 1.5 バジェット割り当て圧力がこの量を超えるまで、作業量の削減を遅らせます。 |
a.Budget.BudgetFactorBeforeReducedWorkEpsilon | 範囲 > 0.0、デフォルト = 0.25 バジェット割り当て圧力が a.Budget.BudgetFactorBeforeReducedWork からこの量を引いた値になるまで、作業量の増加を延期します。 |
**a.Budget.BudgetMs** | 値 > 0.1、デフォルト = 1.0 スケルタル メッシュの作業の実行用に割り当てる時間 (ミリ秒) です。 割り当て超過時には、a.Budget.AlwaysTickFalloffAggression や a.Budget.InterpolationFalloffAggression など、他のさまざまなコンソール変数が有効になります。 |
a.Budget.BudgetPressureSmoothingSpeed | 範囲 > 0.0、デフォルト = 3.0 削減された作業のスロットルに使用されるバジェット割り当て圧力値のスムーズ量です。 |
a.Budget.Debug.Enabled | 値: 0/1 Animation Budget Allocator に対して (それをサポートするビルドで) デバッグ レンダリングを有効にするかどうかを制御します。 |
a.Budget.Debug.ShowAddresses | 値: 0/1 デバッグ レンダリングがデバッグ用コンポーネント データのアドレスを表示するかどうかを制御します。 |
a.Budget.Enabled | 値: 0/1 スケルタル メッシュのバッチ処理システムを有効にするかどうかを制御します。 実行中のスケルタル メッシュがない場合に設定する必要があります。 |
a.Budget.GBudgetPressureBeforeEmergencyReducedWork | 範囲 > 0.0、デフォルト = 2.5 緊急な削減作業のバジェット割り当て圧力を制御します (bAlwaysTick 以外のすべてのコンポーネントに適用されます) 。 |
a.Budget.InitialEstimatedWorkUnitTime | 値 > 0.0、デフォルト = 0.08 スケルタル メッシュ コンポーネントの実行にかかる平均時間をミリ秒単位で制御します。 値はコンポーネントの最初のティックにのみ適用され、それ以降はティックがかかるリアルタイムなコンポーネントを使用します。 |
a.Budget.InterpolationFalloffAggression | 範囲 [0.1, 0.9]、デフォルト = 0.4 補間されたコンポーネントが負荷時にフォールオフするレートを制御します。 値が大きい場合、割り当てられた時間割り当てを超えたときに補間されたコンポーネントの数が大幅に削減されます。 コンポーネントは、時間割り当てを超えたときにのみ補間されます。 |
a.Budget.InterpolationMaxRate | 値 > 1、デフォルト = 6 補間時にティックが発生する速度を制御します。 |
a.Budget.InterpolationTickMultiplier | 範囲 [0.1, 0.9]、デフォルト = 0.75 償却された補間ティックが「通常の」ティックと比較してかかる期待値を制御します。 |
a.Budget.MaxInterpolatedComponents | 範囲 >= 0、デフォルト = 16 スロットリングを開始する前に補間するコンポーネントの最大数です。 |
**a.Budget.MaxTickedOffsreen** | 値 >= 1、デフォルト = 4 画面外でティックさせるコンポーネントの最大数です (最も重要度が高いのは最初のコンポーネントです)。 |
a.Budget.MaxTickRate | 値 >= 1、デフォルト = 10 許容される最大ティック レートです。 これが設定されていると割り当てを超えてしまう可能性がありますが、個々のメッシュの品質を妥当なレベルに保つことができます。 |
a.Budget.MinQuality | 値 [0.0, 1.0]、デフォルト = 0.0 許容される最小品質要求基準です。 品質は NumComponentsTickingThisFrame / NumComponentsThatWeNeedToTick で簡単に決められます。 この値が「0.0」以外の場合は、時間の割り当てを超えてしまう可能性があります。 |
a.Budget.ReducedWorkThrottleMaxInFrames | 範囲 [1, 255]、デフォルト = 20 システム ノイズや負荷ノイズが原因で作業量が減りすぎることを防ぎます。 バジェット割り当て圧力があるときに使用される最大値です。 |
a.Budget.ReducedWorkThrottleMaxPerFrame | 範囲 [1, 255]、デフォルト = 4 ティックあたりの削減した作業との間で切り替えられるコンポーネントの最大数を制御します。 |
a.Budget.ReducedWorkThrottleMinInFrames | 範囲 [1, 255]、デフォルト = 2 システム ノイズや負荷ノイズが原因で作業量が減りすぎることを防ぎます。 バジェット割り当て圧力超過時に使用される最小値 (例:積極的な削減を行ったとき) です。 |
a.Budget.StateChangeThrottleInFrames | 範囲 [1, 128]、デフォルト = 30 システムや負荷ノイズによってスロットル値が頻繁に変わるのを防ぎます。 |
a.Budget.WorkUnitSmoothingSpeed | 値 > 0.1、デフォルト = 5.0 平均作業単位が測定量に収束する速度です。 |