ゲームエンジンであるunityにはfpsを取得する機能があります。
この記事では、
・そもそもfps とは
・Statisticsウィンドウ上でfpsをみる 方法
という基本的な内容から、
・fpsをログで表示する方法
・画面上にfpsを表示する方法
・実機にいれた場合の画面崩れ対策
などの少し応用的な内容についてもわかりやすく解説していきます。
今回はこれらの方法を覚えるために、unityでのfpsの扱いをわかりやすく解説します!
fpsとは
そもそもfpsとは一体なんなのでしょうか?
fpsとはフレームレートの単位のことです。
フレームレートは一秒間に使われる静止画の枚数のことですね。
ゲームの場合一秒間に画像が書き換わる枚数と書いてもよいでしょう。
いずれにせよ、fpsの数値が大きくなるにつれて、画面は滑らかになっていくということです。
逆にfpsの数値が小さくになるにつれて、画面はカクカクになります。
ゲームをやっていてキャラクターがカクカクとぎこちなく動いたことはありませんか?
この現象はfpsの数値が小さすぎるがゆえに起きたことなのです!
エディタ上でも確認できる
それではunityでfpsを表示させていきましょう。
まずは、unityのStatisticsウィンドウ上でfpsを表示させます。
Statisticsウィンドウとは今作っているゲームの様々な情報が見られるウィンドウのことです。
StatisticsウィンドウはGame Viewの右上にあるStatsボタンを押すことで表示されます。
Statisticsウィンドウにはいくつかの情報がありますが、今回はfpsについて書かれている箇所をみていきましょう。
上の画像をご覧ください。赤く縁取られている部分にfpsが書かれています!
この方法でfpsを確認することは非常に簡単ですが、スクリプトから取得することはできませんので、注意してください。
スクリプトから取得し、fpsを画面に表示させる方法は次の章でご紹介いたします!
画面上にfpsを出してみよう!
それでは画面上にfpsを出してみましょう。
そのためには下準備が必要ですので、一緒にやっていきましょう!
下準備
まずはスクリプトを作っていきましょう。
名前は「FpsDisplay」としておきます。名前はなんでも良いので、自分がわかりやすいように決めてください。
スクリプトはProjectのCreateボタンを押し、出てくるC#ボタンを押すことで作れます。
このままでは作ったスクリプトを使うことはできないので、オブジェクトと結びつけます。
それではスクリプトと結びつけるために、今回は空のオブジェクトを作りましょう。
空のオブジェクトはHierarchyのCreateボタンを押し、出てくるCreate Emptyボタンを押すことで作れます。
作成された空のオブジェクトは「GameObject」と表記されています。
それでは空のオブジェクトとスクリプトを結びつけていきましょう。
先ほど作った空のオブジェクトを選択してください。
私の場合はGameObjectという名前ですので、これを選択します。
空のオブジェクトを選択した状態でInspectorにあるAdd Componentボタンを押してください。
すると、Componentの一覧が出てきますのでScriptsを選択し先ほど自分で作ったスクリプトを選択してください。
私の場合は「FpsDisplay」という名前で作ったのでこれを選択します。
オブジェクトとスクリプトが結びついたので、スクリプトの内容が反映されるようになりました。
これで下準備は完了です!
まずはfpsをログで表示しよう!
この記事では二種類のfps算出方法をお教えします。
一つが簡易的にfpsを算出するやり方。
こちらは精度と安定性は落ちますが、簡単なコードで実装できます。
そしてもう一つが精度と安定性の高いやり方。
こちらはクオリティが上がりますが、コードが少しだけ複雑になります。
簡易的なやり方から始めていきましょう。
簡易的なfps計算方法
まずはfpsの計算式について説明しておきます。
fpsは一秒間に画像が書き換わる枚数の単位でしたので、計算式は以下のようになります。
fps = 1(秒) ÷ フレームの間隔(秒)
この計算式をコードで書いていき、ログに表示してみましょう。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class FpsDisplay : MonoBehaviour { private float fps; private void Update() { fps = 1f / Time.deltaTime; Debug.Log(fps); } }
出力結果を見る前にコードの説明をしておきましょう。
まず、float型の変数「fps」を作ります。
その後Update関数の中に処理を書いていきます。
Update関数というのは毎フレームごとに呼ばれる関数のことです。
Update関数の中で1を Time.deltaTimeで割り、その値を変数「fps」に代入します。
Time.deltaTimeには前のフレームと現在のフレームの差分が秒で格納されていますので、上の計算式では「フレームの間隔(秒)」と対応しています。
fps = 1f / Time.deltaTime;の部分が計算式fps = 1(秒) ÷ フレームの間隔(秒)と対応してます。
その後、変数fpsを関数Debug.Logを使ってログに表示させます。
Debug.Logは引数にとった変数をログに表示させる関数です。
コードの説明が終わりましたので出力結果を見てみましょう。
簡易的なやり方でも、そこそこの精度と安定性でfpsを算出できてますね。
しかし上記の画像で赤く囲われている部分を見ればわかる通り、安定していない部分もあります。
続いて少し複雑ですが、より正確かつ安定したやり方でfpsを算出しましょう。
より正確なfps計算方法
ではコードを書いていきます。
using System.Collections; using System.Collections.Generic; using UnityEngine; public class FpsDisplay : MonoBehaviour { // 変数 int frameCount; float prevTime; float fps; // 初期化処理 void Start() { frameCount = 0; prevTime = 0.0f; } // 更新処理 void Update() { frameCount++; float time = Time.realtimeSinceStartup - prevTime; if (time >= 0.5f) { fps = frameCount / time; Debug.Log(fps); frameCount = 0; prevTime = Time.realtimeSinceStartup; } } }
出力結果は、
先ほどのように小さすぎる数値もなく、安定していますね!
それでは、コードの解説をしていきましょう。
やっていることは0.5秒ごとにフレームが書き出された回数を計測し、それを約2倍することでfpsを近似的に出しています。
詳しく解説していきましょう。
Update関数の中身以外はそれほど複雑ではないので、割愛します。
Update関数の中身について解説していきましょう。
Update関数が呼ばれるごとにframeCountに+1(frameCount++の部分)をしていきます。
Update関数は毎フレーム呼ばれるので、frameCountの数値はフレームが書き出された回数を意味します。
次にif文を見ていきましょう。
if文の条件は (time >= 0.5f)となっており、これは0.5秒ごとにif文の中身が処理されることを表しています。
timeという変数にはゲームをスタートしてから経過した時間(Time.realtimeSinceStartup)から変数prevTimeを引いた数が入ります。
変数prevTimeとはif文の最後でゲームをスタートしてから経過した時間(Time.realtimeSinceStartup)が代入される変数です。
つまり変数timeの値は一旦0に戻り秒数が蓄積された後、0.5秒溜まったらif文が処理され再び0に戻ることを繰り返しているのです!
この部分のおかげで0.5秒ごとにfpsを表示できています。
0.5秒ごとに表示する理由は、fpsが安定しやすいからです。
続いてif文の中のfpsについて見ていきましょう。
fpsとは1秒間にフレームが書き出された回数のことでした。
フレームが書き出された回数は変数frameCountが記録しているので、この変数に1秒間という制約をつければfpsの値を出せそうです。
今回のコードでは0.5秒ごとに読み込まれるので、2倍すれば近似的に1秒間にフレームが書き出された回数、つまりfpsの値を出せますね。
それをコードで書いているのがfps = frameCount / time;の部分です。
変数timeには約0.5が入っており、フレームが書き出された回数(frameCount)を割っています。
0.5で割ることは2倍することと同じですので、この部分で近似的にfpsを出せています。
その後、フレームが書き出された回数(frameCount)を0に戻すことで何度もfpsを出せているのです。
以上がコードの説明になります。
少し複雑なコードでしたので、よくわからなかった場合はこの記事を参考にしつつコードをいじってみることで理解を深めてみてください。
画面上にfpsを表示しよう!
では、いよいよ画面上にfpsを表示させていきましょう。
やることはとても簡単で、画面上に表示させるようにコードを付け加えるだけです!
using System.Collections; using System.Collections.Generic; using UnityEngine; public class FpsDisplay : MonoBehaviour { // 変数 int frameCount; float prevTime; float fps; // 初期化処理 void Start() { // 変数の初期化 frameCount = 0; prevTime = 0.0f; } // 更新処理 void Update() { frameCount++; float time = Time.realtimeSinceStartup - prevTime; if (time >= 0.5f) { fps = frameCount / time; Debug.Log(fps); frameCount = 0; prevTime = Time.realtimeSinceStartup; } } // 表示処理 private void OnGUI() { GUILayout.Label(fps.ToString()); } }
出力結果は、
きちんと表示されていますね!
コードをみていきましょう。
新しく付け加えられたのはこの部分です。
private void OnGUI() { GUILayout.Label( fps.ToString() ); }
OnGUIという関数はGUIを表示させる処理を書き込む関数です。
GUIとはグラフィックユーザーインターフェースのことで、ボタンやラベルなどユーザーに見える部分のことを指します。
OnGUIという関数はUpdate関数同様、毎フレームごとに呼ばれる関数ですので注意してください。
今回はOnGUI関数の中に GUILayout.Label関数を使うことでラベルを画面上に表示させています。
GUILayout.Label関数は引数にとったString型の変数をラベルに表示させる関数です。
変数fpsはfloat型ですので、fpsの後に.ToString() をつけることでString型に変換しています。
これで画面上にfpsを表示できるようになりました!
実機に入れた時の画面崩れ対策!
今回のコードでは実機に入れた時にラベルが小さくなっていると思います。
なので、実機の大きさに応じてラベルのサイズを変えましょう。
今回紹介するやり方は、少しらんぼうではありますが文字サイズを大きくするというものです。
OnGUI関数のなかにGUI.skin.label.fontSize = 100;を付け加えてください。
private void OnGUI() { GUI.skin.label.fontSize = 100; GUILayout.Label(fps.ToString()); }
これで実機でも見える大きさになったと思います。
数字の部分(今回なら100)が大きさを表していますので、画面サイズに応じて数値を調整してみてください。
また、今回はコードを書くことでGUIを表示させてきましたが、unityにはCanvasというものを使ったコードを書かずにGUIを設置する方法があります。
複数の画面に対応させたい場合はCanvasを使うと便利です。
まとめ
いかがでしたか?
今回はunityでのfpsの表示について解説しました。
unityではfpsを非常に簡単に表示させられますので、ぜひ使ってみてください!