【Unity】 UniRxでFPSカウンタを作ってみる

  • 13
    Like
  • 5
    Comment
More than 1 year has passed since last update.

UniRxについての記事のまとめはこちら


UniRxを使ってFPSカウンタを作ってみました。

FPSカウンタ
using UnityEngine;
using System.Linq;
using UniRx;
using UniRx.Triggers;

public class FPSCounter : MonoBehaviour
{
    [SerializeField] private int bufferSize = 5; //バッファサイズ
    public ReadOnlyReactiveProperty<float> FpsReactiveProperty;

    private void Awake()
    {
        FpsReactiveProperty = this.UpdateAsObservable()
            .Select(_ => Time.deltaTime)   //Time.deltaTimeに変換
            .Buffer(bufferSize, 1)         //過去bufferSize分バッファ
            .Select(x => 1.0f/x.Average()) //平均値からfps算出
            .ToReadOnlyReactiveProperty();

        FpsReactiveProperty.Subscribe(x => Debug.Log(x));
    }
}

解説

上記のコードは、過去bufferSize分のTime.deltaTimeの平均値を取りそこからFPSを算出しています。
そしてストリームをReadOnlyReactivePropertyに変換し、publicとして公開しています。

注意すべき点としては、FpsReactivePropertyの初期化のタイミングです。
FpsReactivePropertyの初期化が終わる前に別のコンポーネントがFpsReactivePropertyをSubscribeしてしまうとNullReferenceExceptionが発生してしまうので注意しましょう。

追記

Static Propertyにしてしまったほうが取り回しが良いとのご指摘を@neueccさんより受けましたのでそちらのバージョンを記載します。

public static class FPSCounter
{
    const int BufferSize = 5; //サンプル数を変えたい場合はここを変える
    public static IReadOnlyReactiveProperty<float> Current { get; private set; }

    static FPSCounter()
    {
        Current = Observable.EveryUpdate()
            .Select(_ => Time.deltaTime)
            .Buffer(BufferSize, 1)
            .Select(x => 1.0f / x.Average())
            .ToReadOnlyReactiveProperty();
    }
}

こちらのメリットとしては、MonoBehaviourに全く関係ない場所から何も考えずに呼び出してfpsが取得できるという点です。

呼び出し方
FPSCounter.Current.Subscribe( fps => Debug.Log(fps) );