FPS表示およびパフォーマンス最適化ガイド

1. はじめに

本資料では、Unity 6 を用いてビルド後の実行画面上にリアルタイムのFPS(Frames Per Second)を表示する手法を整理し、さらにその表示処理による負荷を最小限に抑えるための最適化ポイントをまとめます。デバッグ用途から製品リリース版まで、用途に合わせた実装例と設定を解説します。


2. FPS表示の基本

  • FPS(Frames Per Second): 1 秒間に何フレーム描画できているかを示す指標。
  • 目的: ゲームやアプリケーションのパフォーマンスを可視化し、最適化効果を定量的に把握する。

3. 実装手法

3.1 方法 1:OnGUI を用いた簡易表示

using UnityEngine;

public class FPSCounterGUI_Throttled : MonoBehaviour
{
    float deltaTime = 0.0f;
    float timeSinceLastUpdate = 0f;
    float cachedFps = 0f;
    const float updateInterval = 0.5f;  // 更新間隔(秒)

    void Update()
    {
        // 平滑化デルタタイム計算
        deltaTime += (Time.unscaledDeltaTime - deltaTime) * 0.1f;
        timeSinceLastUpdate += Time.unscaledDeltaTime;

        // 一定間隔でFPSを更新
        if (timeSinceLastUpdate >= updateInterval)
        {
            cachedFps = 1.0f / deltaTime;
            timeSinceLastUpdate = 0f;
        }
    }

    void OnGUI()
    {
        GUIStyle style = new GUIStyle
        {
            alignment = TextAnchor.UpperLeft,
            fontSize = Screen.height / 40,
            normal = { textColor = Color.white }
        };
        Rect rect = new Rect(10, 10, Screen.width, Screen.height / 20);
        GUI.Label(rect, $"{cachedFps:0.} FPS", style);
    }
}
  • 特徴:
    • デバッグ用途にお手軽
    • Unity の IMGUI (OnGUI) で表示
  • 注意点:
    • OnGUI は毎フレーム内部でレイアウトと描画の2パスを実行するため、UI方式よりやや重い

3.2 方法 2:Canvas+TextMeshProUGUI を用いた表示

3.2.1 シーン準備

  1. Canvas を作成(Screen Space - Overlay 推奨)。
  2. Canvas 下に Text – TextMeshPro を追加。
  3. RectTransform で画面左上など任意の表示位置に調整。

3.2.2 スクリプト例

using UnityEngine;
using TMPro;

public class ThrottledFPSDisplay : MonoBehaviour
{
    [SerializeField] private TMP_Text fpsText;
    [SerializeField] private float updateInterval = 0.5f;  // 更新間隔(秒)

    private float deltaTime = 0.0f;
    private float timeSinceLastUpdate = 0f;

    void Update()
    {
        // 平滑化デルタタイム計算
        deltaTime += (Time.unscaledDeltaTime - deltaTime) * 0.1f;
        timeSinceLastUpdate += Time.unscaledDeltaTime;

        // インターバルごとにテキスト更新
        if (timeSinceLastUpdate >= updateInterval)
        {
            float fps = 1.0f / deltaTime;
            fpsText.text = $"{fps:0.} FPS";
            timeSinceLastUpdate = 0f;
        }
    }
}
  • 特徴:
    • TextMeshPro はバッチ処理に強く軽量
    • 見た目やフォントサイズ・色の調整が容易
    • 更新間引き(throttling)により描画コストを低減

4. パフォーマンス最適化

  1. 更新頻度の制御
    • updateInterval を 0.5~1.0 秒程度に設定することで、文字列整形と UI 更新回数を減少。
  2. 文字列生成の分離
    • OnGUI 版では Update() で FPS 計算&キャッシュのみ行い、OnGUI() ではキャッシュを描画だけ。
  3. 描画方式の選択
    • 製品版には Canvas+TextMeshProUGUI を推奨。OnGUI よりも内部オーバーヘッドが小さい。
  4. フォントサイズ・アンカー調整
    • 画面解像度に依存しないフォントサイズ・アンカー設定で再レイアウトコストを抑制。
  5. カラーとスタイル
    • TMP ではマテリアル設定が可能。白一色であればシェーダー切り替えコストも低い。

5. カスタマイズ例

  • 表示精度fpsText.text = $"{fps:0.0} FPS"; // 小数点以下 1 桁
  • 位置調整Rect rect = new Rect(10, 10, 200, 40); // OnGUI の場合 // UI なら RectTransform のアンカー/ピボットを変更
  • フォントサイズ
    • OnGUI: style.fontSize = Screen.height / 50;
    • TMP: Inspector の Font Size プロパティ

6. まとめ

  • 手軽さ重視 → OnGUI 版(開発中のデバッグ向け)
  • 製品品質重視 → Canvas+TextMeshProUGUI + 更新間引き
  • 最適化ポイント
    1. 更新間隔の調整
    2. 描画処理の分離
    3. 軽量な UI システム利用

上記の組み合わせで、FPS表示による負荷を限りなくゼロに近づけながら、実行画面に常時パフォーマンス指標を表示できます。ぜひプロジェクトに合わせてご活用ください。