【Unity】フレームレートを計算して描画したかったから自作してみた。

どもども。Unityでゲーム作ってる学生です。
今回はフレームレートを計算して描画したかったので、コードを書きました。

え?Unity既存のを使えばいいって?

確かにそうです。
でもビルドした時にも確認したい時ってあるじゃないですか?(僕だけかも)
そういう時にでも使えるのが今から書くScriptなんですね。

ほぼ自己満足で作ってますが、なにか制作の参考になればと。


早速書いていきますよと。

※このFPSDebuggerは「UniRx」を使用しています。
 UniRxについては下記の記事から導入してみてください。

まずUnity内の適当な場所にScriptを作成します。(名前はおまかせします。)

変数を宣言していきます。
色々書いてありますが、コピペで大丈夫です。多分。
using UniRx と using UniRx.Triggersは、のちのち必要なので先に宣言しておきます。

using UnityEngine;
using UniRx;       ← これ必要
using UniRx.Triggers;  ← これ必要

public class FPSDebugger : MonoBehaviour
{
    [Header("DebugMode")]
    [SerializeField] private bool debugMode = true;

    [Header("フレームレート更新速度")]
    private float updateFrame;

    [Header("フォントサイズ")]
    [SerializeField] private int fontSize = 10;

    [Header("最大フレームレート数")]
    public int maxFrameRate;

    [Tooltip("フレームレート更新")]
    private readonly float updateRateSpeed = 1f;

    [Tooltip("Instance")]
    private static FPSDebugger instance;

    [Tooltip("FPS値格納変数")]
    private float fps;

    [Tooltip("フレームカウンター")]
    private int frames;

    [Tooltip("計算するタイミング")]
    private float timeLeft;

    [Tooltip("積み重ねた最大数")]
    private float accum;

    [Tooltip("GUIStyle")]
    private GUIStyle guiStyle = new GUIStyle();
}

続いて関数を書いていきます。
まずはAwake関数。

最初のif文は、「シーンが読み込まれた際に、自分自身が存在しているか」を判断する条件式になります。

シーンに存在していなければ、自分自身が消えないObjectになり、存在していれば、自分自身は抹消されます。

つまり、シーンに1つしか存在しないObjectとして扱われるのです。(すごい!)

その下の updateFrame は、1秒に1回フレームレートを取得する設定にしています。

  1. その下の Application.targetFrameRate = maxFrameRate は、この記事をみているであろう読者様が作成されているアプリケーションの「最大フレーム数」を決めています。

例えば 60と入力すればゲームは60FPSで更新されることになります。
そういうことです。

private void Awake()
    {
        if(!instance)
        {
            instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }

        updateFrame = Time.time + 1f;

        Application.targetFrameRate = maxFrameRate;
    }

続いて。
私が作ったものはOnGUI関数で描画しています。

もしDebugModetrueだったら、下の処理に入ります。

ここではUniRxについて省略しますが、軽く説明をしておきます。
this.UpdateAsObservable() は毎フレーム更新してくれる関数です。
下のWhereは条件がtrueの場合のみ通過する、いわばフィルターです。
Subscribeは実行内容です。 ほぼif文と同じなので分かりやすいかも。

ほんで、中身をごちゃごちゃ書いてますね。
最終的に fps っていうfloat型の変数にフレームレートの値を入れています。

描画に関しては下の3行のみですね。
GUIStyleを使うと色々といじれるらしいので使ってみました。

fps.ToString("f0") で数値をstring型に変換しています。
ちなみに "f0" っていうのは、小数点以下を描画するかどうからしいです。
0にすると整数として描画され、1にすると小数第一位まで描画されます。

ここは人それぞれなので、ご自由に変えてください。

private void OnGUI()
    {
        if(debugMode)
        {
            this.UpdateAsObservable()
                .Where( _=> Time.time >= updateFrame)
                .Subscribe(_ =>
                {
                    timeLeft -= Time.deltaTime;

                    accum += Time.timeScale / Time.deltaTime;

                    frames++;

                    if (0 < timeLeft) return;

                    fps = accum / frames;

                    timeLeft = updateRateSpeed;
                    updateFrame += 1;
                    accum = 0;
                    frames = 0;
                });

            guiStyle.fontSize = fontSize;
            GUI.color = Color.black;
            GUI.Label(new Rect(10f, 10f, 200f, 90f), "FPS : " + fps.ToString("f0") + " FPS", guiStyle);
        }
    }

さあラストスパート!
このScriptだけでは動かないので、シーン上に置いてみましょう。

空のGameObjectを作成して、先程作ったScriptを貼り付け。
シーンが複数ある場合はPrefab化しておくといいでしょう。

インスペクター内の debugMode を true にしておくと、プロジェクトを実行した際に左上にフレームレートが描画されるはずです。多分。

これ、trueにしておくとビルドした際にもフレームレート描画されるんで、別のScriptから描画するかどうか選択できるようにしてもいいかもですね。

夢が広がるねぇ~^^


今回はここらへんで終了します。
今後もUnityのゲーム開発とかツール作成とかの情報を発信していくので、フォローとか色々頂けると励みになります。多分。

それでは。

いいなと思ったら応援しよう!