sh1’s diary

プログラミング、読んだ本、資格試験、ゲームとか私を記録するところ

Unity FPS の設定変更のやり方

Unity のアプリを作っているときに FPS を設定する機会がありました。

レバーレスコントローラーを練習するアプリを作ろうと思ったんで、60FPSに固定してやる必要がありました。ちなみに、こんな雰囲気のアプリになりました。(Android で動かして遊んでます)

やり方をメモ。

FPS の設定は各 scene でやる

さきにどうやったのかを書いてしまう。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class App : ScriptableObject
{
    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
    public static void Initialize()
    {
        var sceneName = SceneManager.GetActiveScene().name;

        if (sceneName.Contains("XXXX"))
        {
            // 60FPS 固定
            QualitySettings.vSyncCount = 0;
            Application.targetFrameRate = 60;
        }
        else
        {
            // 30FPS 固定
            QualitySettings.vSyncCount = 0;
            Application.targetFrameRate = 30;
        }
    }
}

特定のシーンに切り替わったとき、シーンの名前で FPS を60にしたり30にしたりするやり方を採用した。格闘ゲームなら対戦中以外は60FPS必要ないよね、みたいなこと。

Project 設定の Preloaded Assets では正しく動作しなかった

こういうやり方も見つかったので(見た感じいけそうなので)テストしてみたのですが、これはどういうわけか上手く機能しませんでした。(60FPSに変更されませんでした)

また、一度設定するとずっとその FPS のままというのも面倒で、別のところで再設定しようとすると FPS を設定するコードが散らかってしまってどうなんだろう、という感じにも思いました。私の場合はシーンごとでの変更が適切だと設計の考えが落ち着いたので、そのようにしました。

FPS を表示する

やり方はいろいろあると思うけど一例を挙げておく。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;

public class FPSViewer : MonoBehaviour
{
    [SerializeField]
    private float _Interval = 0.1F;

    private TextMeshProUGUI _Text = null;
    private float _Counts;
    private int _Frames;
    private float _Fps;
    private float _Time;

    // Start is called before the first frame update
    void Start()
    {
        _Text = this.GetComponent<TextMeshProUGUI>();
    }

    // Update is called once per frame
    void Update()
    {
        _Time -= Time.deltaTime;
        _Counts += Time.timeScale / Time.deltaTime;
        _Frames += 1;

        if (0 < _Time) return;

        _Fps = _Counts / _Frames;
        _Time = _Interval;
        _Counts = 0;
        _Frames = 0;

        if (_Text != null)
        {
            _Text.text = $"FPS: {_Fps.ToString("00.0")}";
        }
    }
}

関係ないけど、$"FPS: {_Fps:00.0}" の書き方のほうがすっきりしてるかもな、と思いました。

(問題ないとは思うけど)空のオブジェクトに Text - Text Mesh Pro を追加して、コンポーネントの追加でスクリプトを添付する感じです。

SerializeField の属性を TextMeshProUGUI に与えて、Unity の GUI で Text Mesh Pro のテキスト コンポーネントインスタンスを結んでやっても別にいいと思います。

参考