[unity]フレームレート(fps)を設定しよう

フレームレート無制限にすると、勝率が上がる。
60fps 以上じゃないと…。
なんかこのゲーム、もっさりしている。
処理落ちやべぇ。

ゲームをやっていると、こんな言葉を聞くこともあると思います。
古くはシューティングゲーム、今ならアクションゲーム(とくに対戦系)にとって、

自分が入力した細やかなコントロール捌きを、出来る限りきちんとゲーム状況に反映して欲しい

これはプレイが上手くなればなるほど、望まれる傾向が高いです。

60fps とは

今の時代、FPSでググると「ファーストパーソンシューティングゲーム」が1番に表示されることでしょう。主人公視点で進む、3Dガンシューティング。

これの事ではなく、FRAME PER SECOND(1秒間に何回画面を書き換えるか)。
60fps であれば1秒間に 60 回画面を書き換えます。
(絶対ではありませんが、多くのゲームはコントローラの入力検出も、これに合わせて行っていることが多いです)
現在では 120fps とか 無制限(PCやモニタのスペックによる)なんてのもありますね。

現在はフレームレートという言い方が主流だと思いますし、数字が大きいほどいいのですが、オフラインゲームだと 60、オンラインゲームでも 30 を目安にしているゲームが多いです。
液晶モニタになる前のブラウン管モニタにおいては、60 が最速、それが難しい場合は 30(60/2) となっていたため、その名残りですね。
フレームレートを上げるのは簡単ではなく、高画質になればなるほど難しくなっていきます。

unity におけるフレームレート

さて、実はこれ少々複雑です。

Project SettingsTime - Fixed Timestep
デフォルトでは 0.02 となっていますので、50fps ということでしょうか。
これは FixedUpdate が実行される周期です。

Project SettingsQuality- VSync Count

デフォルトでは Every VSync Blank となっており、これはディスプレイのリフレッシュレートによって変動します
もしディスプレイが 60kHz であれば 60fps ですが、90kHz であれば 90fps。
昨今のゲーミングディスプレイだと 120~144kHz とかあったりするようです。60fps の倍以上ですね。
こちらは Update が実行される周期です。

60fps 固定にしたい場合

  1. VSync CountDon't VSync。これを Level ごとに行う
面倒なら High だけ設定、
High 以外チェック外す、も有
  1. スクリプトに次の1行を書く
Application.targetFrameRate = 60; 
  1. Fixed Timestep を 0.166667 などにする

フレームレート(fps)を計測する

設定はしたけれど、本当に fps が出ているのか不安…という方のために計測コードを置いておきます。
Fps メンバに平均フレーム数が入っているので、Debug.Log や Text などに表示してください。

なお、EveryCalcurationTime を小さくすると更新タイミングが早くなります。

using UnityEngine;
using UnityEngine.Profiling;

/// <summary>
/// For debugging: FPS Counter
/// デバッグ用: FPS カウンタ
/// </summary>
public class FPSCounter : MonoBehaviour
{
	/// <summary>
	/// Reflect measurement results every 'EveryCalcurationTime' seconds.
	/// EveryCalcurationTime 秒ごとに計測結果を反映する
	/// </summary>
	[SerializeField, Range(0.1f, 1.0f)]
	float EveryCalcurationTime = 0.5f;
	
	/// <summary>
	/// FPS value
	/// </summary>
	public float Fps
	{
		get; private set;
	}
	
	int frameCount;
	float prevTime;
	
	void Start()
	{
		frameCount = 0;
		prevTime = 0.0f;
		Fps = 0.0f;
	}

	void Update()
	{
		frameCount++;
		float time = Time.realtimeSinceStartup - prevTime;
		
		// n秒ごとに計測
		if (time >= EveryCalcurationTime)
		{
			Fps = frameCount / time;
			
			frameCount = 0;
			prevTime = Time.realtimeSinceStartup;
		}
	}
}

FixedUpdate と Update は完全には同期しない

あくまで近い値にすることは出来ますが、完全に同期しているわけではありません。
そのため、FixedUpdate Update 両方で移動系のロジックを書いたりすると収拾がつかなくなります。

こちらの記事もご覧ください。実際に困って、解決したお話。

返信を残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA