21
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

Organization

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

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) );

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
21
Help us understand the problem. What are the problem?