アニメーションの最適化

さまざまな方法や技術を使用して、Animation ブループリントのパフォーマンスと安定性を最適化します。

Animation ブループリント を使用して Unreal Engine でアニメーション システムを開発すると、複数のアニメーション最適化技術を活用してアニメーション システムのパフォーマンスを向上させることができます。

アニメーションの最適化のプロパティや設定の一部は Unreal Engine Editor のフレームワーク内で使用できますが、その他の方法やツールはプロジェクトの C++ コード ベースで有効化したり、制御することができます。Unreal Engine には、ほとんどのユース ケースに対応できる包括的なツールセットが搭載されていますが、C++ ロジックがアニメーションの評価と再生を最も直接的に制御できる場合があります。

このページで、Unreal Engine のアニメーションの最適化技術の詳細についてご確認ください。

フレームレート

プロジェクトのパフォーマンス、つまりプロジェクトがすべてのゲーム システムを評価し、シーンおよびキャラクターのレンダリングにかかる時間は、中央処理装置 (CPU) と 画像処理装置 (GPU) が一定の時間内に処理できる作業量に基づいて決まります。フレームレートの高いプロジェクトはデータの処理時間が短くなります。これは、フレーム間の時間がフレームレートの低いプロジェクトより短いためです。

プロジェクトの早い段階でどのフレームレートをターゲットにするかを決めることは、重要です。一般的なプロジェクトのフレームレートは 3060 で、それ以上の場合もあります。コンソールやモバイル プラットフォームなど、比較的性能が低いハードウェアで実行されるプロジェクトでは、低いフレームレートが一般的ですが、PC ハードウェアで実行されるプロジェクトでは、多くの場合、ユーザーのハードウェアに基づいて使用可能な帯域幅に合わせてスケーリングできます。ただし、高性能のハードウェアで実行する場合でも、より安定した均一な体験をプレイヤーに提供するためには、プロジェクトを実行するために既定のフレームレートを選択することをお勧めします。

ゲーム アニメーションは、多くの場合、30 fps で作成されます。Unreal Engine では、30 fps のアニメーションを 60 fps で実行したときにシームレスに表示されるように補間することができます。ただし、アニメーションの中には、特定の外観や雰囲気を実現するために、別のフレームレートで作成されるものもあります。

ここでは、同じアニメーションを 30 fps と 60 fps の両方で実行した場合の違いについて確認しましょう。30 fps のアニメーションは含まれている情報が少ないため、低品質のアニメーションが再生されます。60 fps のアニメーションはより高い忠実度で再生されますが、より多くの評価を必要とするため、特に複数のキャラクターやオブジェクトを含むアニメーション システム全体でスケーリングする場合は、プロジェクトで利用可能な帯域幅が減少します。

30 fps

60 fps

![30 fps demo](30fps.gif)(convert:false)

![60 fps demo](60fps.gif)(convert:false)

アニメーションが Animation ブループリントに追加されると、そのブループリントで評価され、ゲーム スレッド を使用してランタイム時にキャラクターで再生されます。ブレンド、IK 評価、物理シミュレーションなどの追加のプロセスを評価する場合は、それぞれのプロセスにより、プロジェクトのパフォーマンス バジェットが減ります。一部のプロセスはシンプルで、評価のためにパフォーマンス バジェットをあまり必要としませんが、より高度な演算を実行して優れた外観のアニメーションが得られるものの、より多くのパフォーマンス バジェットが必要になるプロセスもあります。すべてのアニメーション システムの機能には、その機能に関連して生じるパフォーマンス上の負荷があります。

Unreal Engine の Animation Insights を使用すると、プロジェクトのシミュレーション時にアニメーションのパフォーマンス上の負荷を視覚的に表示することができ、ゲームおよびアニメーション システムでのパフォーマンス バジェットの使用状況を確認することができます。

![ImageAltText](Insights.png)(convert:false)

プロジェクトを最適化するための Animation Insights の設定と使用方法の詳細については、次のドキュメントを参照してください。

animating-characters-and-objects\SkeletalMeshAnimation\Debugging\AnimInsights

マルチスレッド アニメーションの更新を使用する

Unreal Engine では、スレッド内でプロセスが分割されるため、ターゲット ハードウェアは、可能な限り、同時に複数のプロセスを評価することができます。ゲーム スレッド はメイン スレッドで、ゲーム システム、キャラクター アニメーション システム、物理などを含むプロジェクトのブループリントを、フレームごとに順次評価するために使用されます。

![ImageAltText](GameThread.png)(convert:false)

Unreal Engine は、GPU 上で実行される レンダリング スレッド などの他のスレッドを使用して、シーンのレンダリングなどの他の機能を実行します。

![ImageAltText](RenderThread.png)(convert:false)

ターゲット ハードウェアにプロジェクトで使用できる CPU コアが複数ある場合は、プロジェクト内および個々のブループリントに マルチスレッド を実装して、ワークロードを個別のサブスレッドに分割することで、複数のプロセスを同時に評価することができます。これにより、関数を順次ではなく、同時に実行して、プロジェクトの各フレームをランタイム時に評価する時間を大幅に短縮できます。マルチスレッドを適切に実装すると、従来の演算処理技術を使用したプロジェクトよりも高いフレームレートを実現することができます。

![ImageAltText](MultiThread.png)(convert:false)

マルチスレッドは、すべての Unreal Engine プロジェクトでデフォルトで有効になっており、[Project Settings (プロジェクト設定)] で切り替えることができます。メニュー バーで、[Edit (編集)] > [Project Settings] に移動します。[Project Settings] ウィンドウの [General Settings (一般設定)] > [Anim Blueprints (Anim ブループリント)] に移動すると、[Allow Multi Threaded Animation Update (マルチスレッド アニメーションの更新を許可)] を切り替えることができます。

![ImageAltText](AllowMultiThreadedAnimUpdate.png)(convert:false)

マルチスレッド アニメーション ブループリントの評価を活用するには、このシステムを活用したい各 Animation ブループリント内の [Use Multi Threaded Animation Update] プロパティも有効にする必要があります。このプロパティはデフォルトで有効になっていますが、Anim ブループリントの [Class Defaults (クラスのデフォルト)][Optimization (最適化)] で切り替えることができます。

![ImageAltText](ClassDefalts.png)(convert:false)

マルチスレッド アニメーション ブループリントの評価を使用すると、スレッド間でプロジェクトのデータをより細かく制御し、利用できるため、プロジェクトのアニメーション システムのパフォーマンスを向上させることができます。

さらに、[Warn About Blueprint Usage (ブループリントの使用方法について警告する)] を有効にすると、マルチスレッド アニメーション ブループリントの更新を専用の警告と一緒に使用することができます。このプロパティにより、Blueprint Virtual Machine の呼び出しが行われるたびに [Compiler Results (コンパイラの結果)] ログ ウィンドウに警告が表示されます。

マルチスレッド関数

プロジェクトを実行すると、AnimGraph とイベント グラフ上の Animation ブループリントの評価はゲーム スレッドで実行されます。プロジェクトと Animation ブループリントでマルチスレッドの使用が有効になっている場合、必要に応じて、別の関数を使用してアニメーション ブループリント ロジックを作成し、複数のプロセスを複数のサブスレッドで同時に評価することができます。プロセスを複数の関数に分けることで、複数のスレッドを活用してアニメーション システムのボトルネックを減らすことができます。

データ構造体

AnimGraph のデータには FAnimInstanceProxy 構造体を使用してアクセスすることができます。このプロキシ構造体を使用すると、UAnimInstance 構造体にあるデータの大部分にアクセスすることができます。

ほとんどの場合において、AnimGraph ノードの Update プロセスまたは Evaluate プロセス内から UAnimInstance 構造体にアクセスしたり、変更するべきではありません。これらの関数が他のスレッドで実行される可能性があるためです。このようなアクセスを防ぐために、タスクの評価中に FAnimInstanceProxy 構造体へアクセスを防止する GetProxyOnAnyThread 構造体および GetProxyOnGameThread 構造体などのロッキング ラッパーが用意されています。これにより、タスクが強制的にキューに入れられるため、各タスクが前のタスクの完了を待ってから、プロキシ内のデータの読み取りや書き込みを行うことができるようになり、スレッドのオーバーロードが防止されます。

AnimGraph は、Animation Blueprint ノードから UAnimInstance にのみアクセスできます。FAnimInstanceProxy にはアクセスできません。データは、FAnimInstanceProxy::PreUpdate または FAnimInstaceProxy::PreEvaluateAnimation でのバッファリング、コピーなどのプロセスによって、ティックごとにプロキシと交換される必要があります。その後、外部オブジェクトからアクセスする必要があるデータは、FAnimInstanceProxy::PostUpdate でプロキシから交換またはコピーする必要があります。

これは、タスクの実行中にクラスからメンバー変数にアクセスすることができ UAnimInstance の一般的なユース ケースとは相反します。他のクラスから Anim Instance に直接アクセスしないことをお勧めします。代わりに、Anim Instance は他の場所からデータをプルしてください。

カスタムのネイティブ AnimInstance の例

次のコード ブロックは、新しい FAnimInstanceProxy を使用してカスタム ネイティブの AnimInstance クラスをビルドする方法の例です。この例では、内部動作へのアクセスを許可し、プロキシとインスタンスの間での共有データのコピーを回避します。

USTRUCT()
struct FExampleAnimInstanceProxy : public FAnimInstanceProxy
{
    GENERATED_BODY()
    FExampleAnimInstanceProxy()
    : FAnimInstanceProxy()
    {}
    FExampleAnimInstanceProxy(UAnimInstance* Instance);
    virtual void Update(float DeltaSeconds) override
    {
            // Update internal variables
            MovementAngle += 1.0f * DeltaSeconds;
            HorizontalSpeed = FMath::Max(0.0f, HorizontalSpeed - DeltaSeconds);
    }
        public:
    UPROPERTY(Transient, BlueprintReadWrite, EditAnywhere, Category = "Example")
    float MovementAngle;
    UPROPERTY(Transient, BlueprintReadWrite, EditAnywhere, Category = "Example")
    float HorizontalSpeed;
        };
        UCLASS(Transient, Blueprintable)
        class UExampleAnimInstance : public UAnimInstance
        {
        GENERATED_UCLASS_BODY()
        private:
    // The AllowPrivateAccess meta flag will allow this to be exposed to Blueprint,
    // but only to graphs internal to this class.
    UPROPERTY(Transient, BlueprintReadOnly, Category = "Example", meta = (AllowPrivateAccess = "true"))
    FExampleAnimInstanceProxy Proxy;
    virtual FAnimInstanceProxy* CreateAnimInstanceProxy() override
    {
            // override this to just return the proxy on this instance
            return &Proxy;
    }
    virtual void DestroyAnimInstanceProxy(FAnimInstanceProxy* InProxy) override
    {
    }
    friend struct FExampleAnimInstanceProxy;
        }

Animation Fast Path

Animation Fast Path は、AnimGraph の更新内で変数のアクセスを最適化することができます。Animation Fast Path を使用すると、エンジンはブループリントのコードを実行するのではなく (これは、Blueprint Virtual Machine への呼び出しを必要とする)、内部でパラメータをコピーすることができます。現在、コンパイラは以下の構造体最適化することができます。

  • メンバー変数

  • 否定 Boolean メンバー変数

  • ネスティングされた構造体のメンバー

マルチスレッドは、すべての Unreal Engine プロジェクトでデフォルトで有効になっており、[Project Settings] で切り替えることができます。メニュー バーで、[Edit (編集)] > [Project Settings] に移動します。[Project Settings] ウィンドウの [General Settings (一般設定)] > [Anim Blueprints (Anim ブループリント)] に移動すると、[Allow Multi Threaded Animation Update (マルチスレッド アニメーションの更新を許可)] を切り替えることができます。

[Animation Fast Path] オプションは、[Project Settings] でデフォルトで有効になっています。[Animation Fast Path] を切り替えるには、[Project Settings] で [General Settings] > [Anim Blueprints] に移動して、[Optimize Anim Blueprint Member Variable Access] プロパティをオンにします。

![ImageAltText](OptimizeAnimBPMemberVarAccess.png)(convert:false)

Animation Fath Path を活用するには、Animation ブループリントの AnimGraph 内で、ブループリントのロジックが実行されていないことを確認します。

以下のブループリントの例では、AnimGraph がいくつかの浮動小数点値を読み取っています。これらの値は、複数の Blend Space アセットと Blend ノードを制御するために使用されおり、その結果は Final Animation Pose に入力されます。右上に稲妻アイコンが表示されている各ノードは、ロジックが実行されていないため、Fast Path を利用しています。

![ImageAltText](Bolt.png)(convert:false)

グラフにいずれかの形式の計算が追加されると、関連付けられているノードは Fast Path を使用しなくなります。次の例では、float 変数に単純な乗算関数が追加されたため、Blend Space ノードが Fast Path が使用できなくなっています。このグラフがコンパイルされると、この変更を示す稲妻アイコンが削除されます。

![ImageAltText](multiply.png)(convert:false)

Fast Path メソッド

以下は、Animation ブループリントで Fast Path 変数へのアクセスを実装するために使用できるメソッドです。

メンバー変数に直接アクセスする

Fast Path を使用すると、直接ブール変数の値にアクセスして読み取り、ポーズを決定することができます。

![ImageAltText](bool.png)(convert:false)

ここでは、Blend Poses by bool ノードが、直接アクセスではなく、ブールの状態を決定するロジックを実行する際に、Fast Path 変数へのアクセスを回避していることがわかります。

![ImageAltText](equals.png)(convert:false)

ネスティングされた構造体のメンバーにアクセスする

rotator 変数などネスティングされた構造体を分割して、そのコンポーネントに直接アクセスすることができます。グラフ内の変数を右クリックし、表示されるコンテキスト メニューから [Split Struct Pin (構造体ピンを分割)] を選択すると、構造体を直接分割することができます。これにより、ノードが変数に変換され、そのコンポーネント値に直接アクセスすることができます。

![ImageAltText](split.png)(convert:false)

Break-Struct ノードを使用するメンバーにアクセスする

また、Break Struct ノードを使用してネスティングされた構造体を分割し、そのコンポーネント値に直接アクセスすることもできます。

![ImageAltText](breaknode.png)(convert:false)

Break Transform など、一部の Break Struct ノードは、現在 Fast Path を使用しません。これは、単にデータをコピーするのではなく、内部で変換を行うためです。

Warn About Blueprint Usage (ブループリントの使用方法について警告する)

アニメーション ブループリントで Fast Path が使用されていることを確認するには、[Warn About Blueprint Usage] プロパティを有効にします。[Warn About Blueprint Usage] を有効にすると、AnimGraph から Blueprint Virtual Machine が呼び出されたときに、コンパイラが [Compiler Results] パネルに警告を表示します。

[Warn About Blueprint Usage] を有効にするには、Animation ブループリント[Class Settings (クラス設定)][Optimization] でこのオプションを有効にします。

![ImageAltText](Warn.png)(convert:false)

[Warn About Blueprint Usage] プロパティを有効にして、AnimGraph でブループリント ロジックを実行すると、変数が Fast Path を使用してアクセスできるときは、[Compiler Results] パネルに警告メッセージが表示されます。警告メッセージのリンクをクリックすると、警告の原因となっている箇所に焦点を絞ってグラフが表示されます。これにより、最適化が必要な箇所を追跡することができ、最適化できる可能性のあるノード変数アクセスを特定することができます。

![ImageAltText](warngraph.png)(convert:false)

一般的なヒント

プロジェクトのアニメーション システムのパフォーマンスの検討を始めたら、最適化プロセスの次のガイドラインを考慮することができます。各プロジェクトには独自の最適化要件があり、プロジェクトの規模とスコープに基づいて、より踏み込んだ変更が必要な場合がありますが、以下のガイドラインでは、ほとんどのプロジェクトにメリットがもたらされる一般的なアプローチを提供します。

  • Parallel Updates の条件が満たされていることを確認します。

    • UAnimInstance::NeedsImmediateUpdate 構造体では、ゲーム スレッド で実行されるアニメーションの更新フェーズを避けるために満たす必要のあるすべての条件を確認することができます。キャラクターの動きに ルート モーション が必要な場合は、並列更新を行うことはできません。キャラクターの動きはマルチスレッド処理ではないためです。

  • Blueprint Virtual Machine の呼び出しを回避する

    • ブループリントのネイティブ化 を C++ コードにすることを検討します。

    • Animation ブループリントの イベント グラフ ではロジックを実行しないことをお勧めします。代わりに、カスタムの UAnimInstance と FAnimInstanceProxy 派生クラスを使用して、FAnimInstanceProxy::Update または FAnimInstanceProxy::Evaluate の間にプロキシでロジックを実行します。これらは、ワーカー スレッドで実行されるからです。

    • Animation ブループリントの アニメーション グラフ 内で、Fast Path を使用するようにノードを構築します。

    • [Project Settings][Optimize Anim Blueprint Member Variable Access] プロパティを有効にします。これは、そのクラスのメンバー変数に直接アクセスする Animation Blueprint ノードが、Blueprint Virtual Machine の呼び出しを回避する最適化されたパスを使用するかどうかを制御するためです。

    • 一般的に、AnimGraph の実行で最も負荷がかかるのは、Blueprint Virtual Machine の呼び出しです。この呼び出しを避けることが、Animation ブループリントのパフォーマンスを最大化するうえで重要です。

  • 可能な場合は、Update Rate Optimizations (URO) を使用します。

    • URO は、アニメーションのティックの頻度が過剰にならないようにします。これをどのように適用するかはプロジェクトのニーズに応じて異なります。ただし、ほとんどのキャラクターにおいて、適切な距離で 15Hz 以下で実行する更新レートをターゲットにして、補間を無効にすることをお勧めします。

    • URO を有効にするには、スケルタルメッシュ コンポーネントの [Details] パネルで [Optimization] セクションに移動し、[Enable Update Rate Optimizations] プロパティを選択します。その後、AnimUpdateRateTick() 構造体を使用して、ブループリントのティック レートを設定し、確認することができます。

      ![ImageAltText](EnableURO.png)(convert:false)

      • 必要に応じて、スケルタルメッシュ コンポーネントの [Details] パネルで [Display Debug Update Rate Optimizations] プロパティを有効にすることで、シミュレーション中にプロジェクトに適用される URO のレートのオンスクリーンのデバッグ表示を使用することもできます。

      ![ImageAltText](EnableURODebug.png)(convert:false)

  • キャラクターがその 物理アセット にアクセスする必要がない場合は、[Component Use Fixed Skel Bounds] を有効にします。

    • スケルタルメッシュ コンポーネントの [Details] パネルで、[Component Use Fixed Skel Bounds] プロパティを有効にします。

      ![ImageAltText](FixedSkel.png)(convert:false)

      • これにより、物理アセットの使用が省略され、代わりにスケルタルメッシュで定義された固定の境界が常に使用されます。

      • これにより、フレームごとのカリング用のバウンディング ボリュームの再計算も省略されるため、パフォーマンスが向上します。

その他の考慮事項

Animation Insights を使用してプロジェクトのプロファイリングを行うと、ワーカー スレッドがこのプロセスを完了した後に、メイン スレッドでスケルタルメッシュに対して FParallelAnimationCompletionTask が実行されていることがわかります。このプロセスは、並列更新の条件が満たされると、プロファイルで見られるメイン スレッド作業の大半の部分です。通常、このプロセスは、セットアップに応じて、次のような複数のプロセスで構成されます。

  • 物理オブジェクトの更新など、プロジェクトのコンポーネントの動きを計算します。

    • 可能な限り、実際に物理を必要としないものについては、物理の更新を回避します。これは、FParallelAnimationCompletionTask の最も大きな削減につながります。

  • アニメーションの通知を発行します。

    • Blueprint Virtual Machine の呼び出しを避けるため、すべての通知はブループリント ベースではない必要があります。

    • アニメートしたオブジェクトのライフタイムに影響を与える可能性があるため、通知は ゲーム スレッド で実行する必要があります。

  • URO が有効な場合、アニメーションを補間します。

  • マテリアル カーブまたはモーフ ターゲットのカーブを使用している場合、カーブをブレンドします。

Unreal Engine のドキュメントを改善するために協力をお願いします!どのような改善を望んでいるかご意見をお聞かせください。
調査に参加する
キャンセル