【Unity】フレームレート(FPS)と処理時間の関係【ゲーム開発】
パフォーマンスに関してよく話題にのぼるのがフレームレートの話。FPS(Frames Per Second)と略されることが多く、「あのゲーム、15FPSだからカクカクしてるよね」とか、「このゲーム120FPSでヌルヌル動くぜ!」なんて文脈で使われます。
フレームって何? という場合は以下の記事も参考までに。
UnityではQualitySettingsの「vSyncCount」を設定したり、スクリプトから「Application.targetFrameRate = 60;」のように目標のフレームレートを設定できます。
こうしたフレームの話と切り離せないのが「処理落ち」です。
ゲームはできれば高いフレームレートにした方が動きがスムーズになるので嬉しいのですが、毎フレーム処理を行っているUpdate()などで処理時間が多くかかると、フレームの描画タイミングに間に合わないことがあります。
こうしたフレームと処理時間の関係をおさらいしてみるのがこのページの目的です。
ゲームにおけるフレーム
ゲームにおけるフレームは、画面に描画(レンダリング)された画像のことを指します。ちょっと動くごとに画像を描画していき、それを連続的に表示することであたかも動いているかのように表現しています。
映画のフィルムをみたことがあればそれをイメージすると良いと思います。
画面のイメージとしてはパラパラ漫画が近いかもしれません。ここに音がついたり、プレイヤーの入力に応じてキャラクターの動作を変えたりするのがゲームの肝となる部分です。
決められた時間ごとに画像を生成していくため、その時間内に処理を終わらせて、画像を描画する必要があるんですね。
フレームあたりの処理時間
1フレームあたりに許された処理時間は、1秒をフレームレートで割ることで算出できます。
フレームレート | 処理時間 |
15FPS | 1 / 15 ≒ 0.0667秒 |
30FPS | 1 / 30 ≒ 0.0333秒 |
60FPS | 1 / 60 ≒ 0.0167秒 |
120FPS | 1 / 120 ≒ 0.0083秒 |
1フレームでこの処理時間を超えてしまうと、目標としたタイミングで画面が描画されないため
カクカクした状態、つまり処理落ちが発生します。
フレームレートが高くなるほど見た目はスムーズに動作していますが、処理時間の猶予がシビアになるため、スクリプトの処理のパフォーマンスをより厳密に調整していく必要があります。
どのフレームレートを選択すべきかは作成したいゲームによるのですが、アクションやレース、音ゲーなど、ユーザーの操作に対してズレがあると困るゲームはなるべく高いフレームレートにする方が良いです。
一方で、じっくり考えながら操作できるRPGやシミュレーションゲームであれば多少フレームレートを落としても良いと思います。
演出をするときだけ60FPS、ユーザーが操作を行うタイミングでは30FPSなど、スクリプトから動的に変更するのも手です。
フレームレートの確認
フレームレートを確認するには、GameウィンドウのStats(統計情報)の機能を使うか、Profilerを使うと便利です。
statsによる確認
『Stats』のボタンをクリックすると統計情報が表示されるようになり、ゲームを実行しているときにどんどん更新されていきます。
この中にあるCPUの項目を確認することで、処理時間の目安を知ることができます。例えば以下の画像の例であれば、CPUの処理時間はmainが3.2ms(=0.0032秒)なので、大体300FPSくらいは出る処理時間になっています。Graphicsの右側に表示されているFPSの値がこの目安を表しています。
実際にはPCやスマホの画面描画のタイミングに合わせるので、60FPSだったり30FPSのタイミングまで描画を待つことが多いです。高性能なPCモニタなら90FPSや120FPSで画面を更新できることから、ハイエンド向けのゲームならそこまでの処理時間を意識すると良いでしょう。
Profilerによる確認
Profiler(プロファイラー)を使うとCPUの処理時間をグラフで確認できるので、一目でフレームごとの処理時間が分かります。
例えば上の画像はProfilerの『CPU Usage(CPU使用率)』の項目です。グラフの中で『16ms (60FPS)』だったり『10ms (100ms)』とラベルが貼られている横線がありますが、これがFPSの目安を表しています。
この画面を撮影したゲームでは毎フレームの処理をほとんどいれていないので、たまにピークがあるくらいでほぼ100FPS以上は出せるようになっています。
処理時間の項目についてはグラフの中で色付きで表示されるため、処理時間がかかっている項目を特定して調整することで、安定したフレームレートにすることができます。
実機ならデバッグ用のスクリプトを入れると便利
実機で確認するなら、ゲーム画面にFPSを表示するスクリプトを作っておくと便利です。
Update()が呼ばれるたびにフレームのカウントを増やし、1秒経過した時点で呼ばれていたフレームの数がFPSだと判断できます。
例えば以下のようなコードで画面上にフレームレートを表示することができます。個人的な好みでTextMesh Proを使っていますが、Unity標準のテキストを使ってもOKです。
fpsの計算部分では、fpsCountがint型なので計算結果がint型にならないように1.0fをかけています。
このスクリプトをシーン内のオブジェクトにアタッチして、フレームレートを表示するTextMesh Proオブジェクトを参照させると以下のようにフレームレートを表示してくれます。
この画面はUnityのEditorでゲームを実行しているものを撮影していることから、フレームレートを上げられるだけ上げていますね。まさか120FPSまで出るとは思ってなかったのでびっくりです(笑)
他のプラットフォームでは、スマホなら大体30FPS、コンシューマゲーム機なら大体60FPSになると思います。この辺りは画面と同期するかどうかの設定にもよるので想定されるFPSをうまく調整するようにしてください。
画面との同期
冒頭でもちょっと触れたQualitySettingsの「vSync Count」についてですが、これは画面と同期するかどうかの設定です。メニューバーの [Edit] -> [Project Settings] から『Quality』タブを開くと「vSync Count」の設定を確認することができます。デフォルトでは [Every V Sync] となっていて、画面と同期するようになっています。
なので、PCなら可能な限りフレームレートを上げてくれますし、例えばiPhoneなら30FPSになるように描画しようとします。
このあたりも必要に応じて設定するようにすると良いでしょう。
また、画面と同期させない場合には、自分でスクリプトの中からターゲットとなるFPSを設定することもできます。例えば以下の例ではStart()の中で目標とするFPSを60に設定しています。
画面と同期するようにするとそちらが優先されますが、同期しない場合に自力でセットすると良いでしょう。
また、この目標FPSはあくまで目標であって、処理時間が長くなれば処理落ちが発生するので調整はしっかりしておきましょう。
まとめ
FPSを確認するにはGameウィンドウのStatsの機能を使うか、Profilerを使います。目標となるFPSの設定はQuality設定、またはスクリプトから自分で行うと良いでしょう。
フレームレートに関してはテストに入る前の開発期間中から意識できると手戻りが少なくて済むので、ある程度ゲームができてきたらFPSを確認してみてください。
ゲーム開発の攻略チャートを作りました!
-
前の記事
【ゲーム開発】ゲームの遊び方が分かるヘルプ画面があると安心 2020.08.18
-
次の記事
【Unity】フレームレートを上げるとバッテリーにも影響が出る 2020.08.20
コメントを書く