この記事はN・S高等学校 (1) Advent Calendar 2021 の13日目の記事です。
はじめまして。
学校法人角川ドワンゴ学園のプログラミングスクールN Code Laboのnaoki_sakanoといいます。
この記事を書いているときはN Code Labo横浜教室の教室長を担当しています。
N Code Labo(以下、Nラボ)が学校法人角川ドワンゴ学園が運営する小〜高校生向けのプログラミングスクールで、新宿・秋葉原・横浜・梅田(New!!)に教室があります。
また、Zoomを用いたネットコースもあり、Unityをはじめとした実践的なプログラミングのコンテンツを提供しています。
今回は、Unityでよく使うupdate,FixedUpdate,OnGUIの仕様の違いを紹介します。
検証しようと思ったきっかけ
とあるN Code Labo横浜の生徒がタイピングゲームを作っていました。
N Code LaboのUnity教材の中に、C#の基礎を学習する教材があります。
While文の学習の過程の挑戦問題に「タイピングゲームを作ってみよう」(ヒントなし)というものがありまして、それを作ったのが9月の話です。
その後、そのタイピングゲームを発展させる形で学習を進めており、キー入力に応じて画面表示を変える処理を作っていました。
Textの変更となりますので、OnGUIを使うのですが、どうも一度のキー入力で何度も作動してしまうことがありました。
試しに、画面表示をCounterにしてみたところ、1度の入力で0→2となりました。
明らかにおかしいです。
そのため、以下の検証を行うこととしました。
先に結論
update(毎フレームに1回呼び出される)
FixedUpdate(0.02秒ごとに呼び出される)
OnGUI(フレームごとに複数呼び出される)
さくっと検証
上記だけだとピンと来ないので、まずは検証用のプログラムを作ります。
「Create Empty」で空のオブジェクトを作って、以下のスクリプトを当ててみます。
仕組みは簡単で「スペースを押したらログを出す」というプログラムで、それをUpdate,FixedUpdate,OnGUIにそれぞれ当てているだけです。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class keydown : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Debug.Log("Press void Update");
}
}
void FixedUpdate()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Debug.Log("Press void FixedUpdate");
}
}
void OnGUI()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Debug.Log("Press void OnGUI");
}
}
}
検証結果
結果は以下のようになりました。
Updateが1回、FixedUpdateが4回、OnGUIが8回実行されています。
なぜこうなるのか?
公式のドキュメントを読むと、以下のようなことが書いてありました。
FixedUpdate: FixedUpdate はしばしば、Update よりも頻繁に呼び出されることがあります。フレームレートが低く、フレーム間で呼び出されない可能性がある場合は、1 フレームに複数回呼び出される場合があります。
フレームレートが高い場合は複数のフレームの間でも呼び出されないことがあります。すべての物理演算とアップデートは FixedUpdate のすぐ後に発生します。
FixedUpdate 内で移動の計算を行う場合は、 Time.deltaTime で値を乗算する必要はありません。なぜなら FixedUpdate は、フレームレートとは関係なく、信頼性のあるタイマーで呼び出されるからです。Update: Update は、 1 フレームにつき 1 度呼び出されます。これは、フレームのアップデートの主となる関数です。
OnGUI: GUI イベントに応じて、フレームごとに複数回呼び出されます。レイアウトおよび再描画イベントが最初に処理され、その後にレイアウトおよびキーボード/マウスイベントが各入力イベントに対して処理されます。
Update,FixedUpdate,OnGUIはそれぞれ独立した処理になっており、Unityの処理の中で順番に処理されていることが分かりました。
Updateはフレームに必ず1回作動しますが、フレームレートが高ければ実行回数はフレームレートに比例して増えていきます。
一方、FixedUpdateは時間に比例しますので、フレーム毎かどうかは関係ありません。正確な時間を計って出したい処理に向いてそうです。
OnGUIは元々名前のとおり、GUI周りをサポートしてくれるので、描画やレンダリング周りで役に立ちます。
結論:使い分けが大切
大変、普通なことですが、大切なことです。
この検証からわかったことは、フレームレートの違いによって、実行される処理に変化が生じる、ということです。
そのため、行いたい処理がどのような操作なのかを考えた上で使い分けていくことが必要になります。
ちなみに、この仕様を調べる過程でLastUpdateというものの存在を初めて知りました。
最後に宣伝
N Code Laboは小〜高校生向けのプログラミングスクールで、多分子供向けプログラミングスクールでは珍しいオブジェクト指向も"しっかり"学ぶことができるプログラミングスクールです。
通学する教室では無料体験授業を、ネットコースでは水曜と土曜に説明会を実施していますので、よかったら一度覗いてみてください。
ちなみに職員と講師の採用もしておりますので、よかったらお問い合わせください。