FrameTimingManager は、アプリケーションの個々のフレーム中のパフォーマンスに関する詳細なタイミングデータを取得する API です。このデータを使用してフレームを評価することで、アプリケーションがパフォーマンス目標に達しない理由を理解することができます。
以下のような場合に FrameTimingManager を使用してください。
フレームタイミングは、プロファイラー からのデータを置き換えるものではありません。アプリケーションを高レベルでプロファイリングした後に、FrameTimingManager を使用して特定の詳細を調査してください。FrameTimingManager は、データを記録する時にパフォーマンスを低下させるため、アプリケーションのパフォーマンスを正確に測定することはできません。
ヒント: FrameTimingManager は、開発用プレイヤービルドでは常にアクティブです。
リリースビルド用に Unity エディターで FrameTimingManageer を有効にするには、以下の手順に従ってください。
OpenGL プラットフォームを使用している場合は、GPU 使用率を測定するために OpenGL: Profiler GPU Recorders プロパティも有効にする必要があります。これは以下の手順で行えます。
ノート: バージョン 2021.2 以前の Unity では、OpenGL Profiler GPU Recorder が Frame Timing Stats プロパティを無効にするため、これらを併用できません。
FrameTimingManager の記録するデータにアクセスするには、以下のいずれかの方法を使用してください。
以下の手順で、カスタムプロファイラーモジュールにフレームタイミングデータを表示できます。
以下の表は、Frame Timing Stats を有効にすると使用可能になる各カウンターの役割を説明したものです。
測定項目 | 説明 |
---|---|
CPU Total Frame Time (ms) | CPU フレーム時間の合計 (ミリ秒単位) です。Unity はこれを、2 つのフレームの終了時点と終了時点の間の時間として (オーバーヘッドやフレーム間の待機時間も含めて) 計算します。 |
CPU Main Thread Frame Time (ms) | フレームの開始から、メインスレッドがそのフレーム中に実行した作業を終了するまでの時間 (ミリ秒単位) です。 |
CPU Main Thread Present Wait Time (ms) | フレーム中で Present() を待機するのに費やされた CPU 時間です。 |
CPU Render Thread Frame Time (ms) | Render Thread での処理の開始から、Unity が Present() 関数を呼び出すまでの時間 (ミリ秒単位) です。 |
GPU Frame Time (ms) | GPU の、単一のフレームのレンダリングの開始時間と終了時間の差 (ミリ秒単位) です。 |
FrameTimingManager API を使用してタイムスタンプ情報にアクセスできます。FrameTimingManager は、各変数に、フレーム中で特定のイベントが発生する時間を記録します。
以下の表は、この API を通して利用可能な値を、Unity がフレーム中に実行する順番で示したものです。
プロパティ | 説明 |
---|---|
frameStartTimestamp | フレームが開始する CPU 時間です。 |
firstSubmitTimestamp | Unity がこのフレーム中で最初のジョブを GPU に投入する CPU 時間です。 |
cpuTimePresentCalled | Unity が現在のフレーム用に Present() 関数を呼び出す CPU 時間です。 |
cpuTimeFrameComplete | GPU がフレームのレンダリングを終了して CPU に割り込む CPU 時間です。 |
FrameTimingManager の C# API の代わりに ProfilerRecorder API を使用して FrameTimingManager の値を読み取ることができます。この利点は、ProfilerRecorder API を使用すると、特定のカウンターにレコーダーが設定した時にのみ FrameTimingManager が値を記録することです。この動作のおかげで、どのカウンターがデータを収集するか制御できるようになるため、FrameTimingManager がパフォーマンスに与える影響を抑えられます。
以下の例は、ProfilerRecordAPI を使用して CPU Main Thread Frame Time 変数のみを追跡する方法を示しています。
using Unity.Profiling;
using UnityEngine;
public class ExampleScript : MonoBehaviour
{
string statsText;
ProfilerRecorder mainThreadTimeRecorder;
void OnEnable()
{
mainThreadTimeRecorder = ProfilerRecorder.StartNew(ProfilerCategory.Internal, "CPU Main Thread Frame Time");
}
void OnDisable()
{
mainThreadTimeRecorder.Dispose();
}
void Update()
{
var frameTime = mainThreadTimeRecorder.LastValue;
// Your code logic here
}
}
FrameTimingManager は、4 フレーム分の固定された遅延を含んだ結果を提供します。これは、タイミングの結果が各フレームの終了時にすぐに得られないからで、このために FrameTimingManager はフレームの CPU および GPU データを取得する前に待機するからです。
この遅延は、正確なタイミングの結果を保証するものではありません。なぜなら、GPU が結果を返すために使用可能なリソースを持っていなかったり、正しく結果を返せない可能性があるからです。
FrameTimingManger は、以下のような特定の状況下では、FrameTimeComplete タイムスタンプの生成方法を変更します。
Apple デバイスの Metal GPU など、タイルベースのディファードレンダリングアーキテクチャを使用する GPU では、レポートされる GPU 時間が、レポートされるフレーム時間よりも大きくなる可能性があります。
これは、GPU にかかる負荷が高い時や、GPU パイプラインが満杯の時に発生する可能性があります。このような場合、GPU は、一部のレンダリングフェーズの実行を延期する場合があります。FrameTimingManager はフレームのレンダリングの開始と終了の間の時間を測定するため、フェー ズ間にギャップがあると、レポートされる GPU 時間が増大します。
以下の例では、GPU が Vertex キューから Fragment キューにジョブを渡すため、使用可能な GPU リソースがありません。このため、GPU のグラフィックス API は、次のフェーズの実行を延期します。このような場合、GPU の時間測定にフェーズの処理時間とその間のギャップが含まれることになります。その結果、FrameTimingManager が、予想よりも高い GPU 時間測定値をレポートします。
プロパティ | 説明 | サポート | コメント |
---|---|---|---|
Windows | DirectX 11 | あり | |
DirectX 12 | あり | ||
OpenGL | あり | ||
Vulkan | あり | ||
macOS | Metal | あり | タイルベースのディファードレンダリング GPU の動作により、総フレーム時間よりも大きな GPU 時間測定値がレポートされる可能性があります。 |
Linux | OpenGL | 場合によって推奨 | GPU 時間計測をサポートしていません。 |
Vulkan | あり | ||
Android | OpenGL ES | あり | |
Vulkan | あり | ||
iOS | Metal | あり | タイルベースのディファードレンダリング GPU の動作により、総フレーム時間よりも大きな GPU 時間測定値がレポートされる可能性があります。 |
tvOS | Metal | あり | タイルベースのディファードレンダリング GPU の動作により、総フレーム時間よりも大きな GPU 時間測定値がレポートされる可能性があります。 |
WebGL | WebGL | 場合によって推奨 | GPU 時間計測をサポートしていません。 |