UnityのUpdateとFixedUpdate、LateUpdateメソッドについて

記事内に広告が含まれています。

今回はUnityで当たり前のように使っているUpdateメソッド、FixedUpdateメソッド、LateUpdateメソッドについてみていこうと思います。

これらのメソッドはMonoBehaviourクラスを継承して作成したクラスで呼ばれるようになります。

UnityでC#のファイルを作成した時にデフォルトでMonoBehaviourクラスを継承して新しいクラスが作成されていると思います。

例えばC#でTestClassというファイルを作成したら

のようにMonoBehaviourを継承してTestClassが作成され、StartとUpdateメソッドがデフォルトで用意されています。

FixedUpdateやLateUpdateも記述すれば呼ばれるようになります。

JavaScriptで新しいファイルを作成した場合は明示的に表示されていませんがMonobehaviourクラスを継承して作成されています。

ちなみにこのMonobehaviourクラスを継承して作られたクラスはインスタンス化は出来ません。

スポンサーリンク

Updateメソッド

ゲームで何らかの処理をしようと思ったらUpdateメソッド内に記述する事が多いと思います。

Updateメソッドは毎フレーム呼ばれるので、キーボードを押したか?指定した時間が経過したか?目的地についたかどうか?

等を判断する時に便利です。

Updateメソッドが呼ばれるタイミングはアニメーションがレンダリング(画像の生成等)される前に呼ばれます。

なのでUpdateでキャラクターの位置等を変更し、その後キャラクター等のレンダリングが行われるという感じになります。

Time.deltaTime

Updateメソッドはコンピューターの性能によって呼ばれる回数が変わってくるためキャラクターの移動をさせる時等は性能差を考慮したスクリプトにする必要があります。

その為に使用するのがTime.deltaTimeです。

このTime.deltaTimeは最後のフレームを終了するのに要した時間をあらわします。

最後のフレームを終了するのに要した時間って何!?となりそうですが・・・・(^_^;)

つまりは前回のUpdateから今のUpdateが呼び出されるまでの時間ということですね。

その為

↑のようにスクリプトを作成し、何らかのゲームオブジェクトに設定すればこのゲームオブジェクトが登場してからの経過時間を調べる事が出来ます。

経過時間計測結果

↑が実行例です。

Updateメソッド内でキャラクターの移動をさせる処理を記述する事が多いと思いますが、性能差を考えこのTime.deltaTimeを移動値にかけて利用するようにします。

基礎的なキャラクターの移動に関しては

Unityでキャラクターの移動をプログラミングしてみる
Unityで3Dキャラクターモデルを配置し、キャラクターをCharacterControllerの機能を使って移動させるようなプログラミングをしてみます。

を参照してください。

LateUpdateメソッド

LateUpdateメソッドはUpdateメソッドが呼ばれた後に実行されるメソッドで中身としてはUpdateと同じです。

用途としてはキャラクターが移動した後にカメラをキャラクターに追従させる時等に使用します。

Updateメソッド内でキャラクターの移動とカメラの追従を同時に行おうとするとうまくカメラが追従してくれない事があります。

そこで、Updateメソッドでキャラクターの移動をさせた後にLateUpdateメソッドでカメラがキャラクターを追従するようにするとうまく出来たりします。

Updateメソッドで何らかの処理をした後に実行したいものがあるならばLateUpdateメソッドを利用するといいですね。

LateUpdateメソッドに関しては他に書く事ないなぁ・・・・(^_^;)

実際に使っている記事は

Unityのゲームキャラクター操作をすべてマウス操作で行う
Unityのゲームで使用するキャラクターの移動やカメラの回転、カメラのズーム機能、カメラの壁対策、人との会話、敵を攻撃等のすべてをマウス操作で行う為の機能を作成していきます。

やブログの右上にある『サイト内検索が出来ます』でLateUpdateで検索して頂くといくつかの例が出てきますので参照してください。

FixedUpdateメソッド

FixedUpdateメソッドはUpdateメソッドと似ていますが、Updateメソッドはゲームオブジェクト等の動作のレンダリング前で、

FixedUpdateメソッドは物理挙動の更新の直前に呼ばれます。

Updateメソッドはコンピュータの性能差で呼ばれる回数が変わりますが、FixedUpdateメソッドは固定フレームレート(1秒間に呼ばれる回数が同じ)で呼ばれます。

フレームレートは1秒間に呼ばれるフレームの回数なのでfps(フレームパーセカンド)で表現します。

1秒間に30回フレームが呼ばれるとしたら30fpsという事ですね。

このフレームレートはUnityメニューのEdit→Project Settings→Timeで設定出来ます。

FixedTimeStepの設定

↑のようにTimeを選択します。

TimeManagerのインスペクタ

↑のようにインスペクタにTimeManagerが表示され、Fixed TimeStepでフレームレートを変更出来ます。

デフォルトで0.02となっていて0.02秒間に1回フレームが呼ばれる設定になっています。

つまり1フレーム/0.02秒ですね、これを1秒間に直していくと100フレーム/2秒→50フレーム/1秒、つまり50fpsという事になります。

よってFixedUpdateメソッドはデフォルトの設定で1秒間に50回呼び出されると言う事になります。

Fixed TimeStepを変更すれば固定フレームレートを変更出来るのでここを1にすれば1秒毎にFixedUpdateメソッドが呼ばれるようになります。

もっと多くFixedUpdateメソッドが呼ばれるように小さい値を設定する事も出来ますが、FixedUpdateメソッド内での処理が多ければそれだけ処理負荷がかかります。

ここら辺は

重要なクラス - Time - Unity マニュアル
Unity の Time クラスは、プロジェクトで時間関連の値を扱う重要な基本プロパティを提供します。

Unity公式のタイムとフレームレートの管理のページをご覧ください。

Rigidbodyを使ってゲームオブジェクトに力を加える時はUpdateメソッドではなくFixedUpdateメソッドで行うのがいいとチラホラ見た事があるんですが、

その理由はFixedUpdateメソッドの呼ばれるタイミングが物理挙動の更新の直前に呼ばれる、固定フレームレートで呼ばれるというのがあるんですね。

UpdateメソッドとFixedUpdateメソッドのテスト

UpdateメソッドとFixedUpdateメソッドを見てきたので実際にテストして確認してみましょう。

両方のメソッド内でフレームレートを計算してコンソールに表示してみます。

Updateメソッド内でUpdateメソッドが呼ばれた回数を計算した秒数で割ってfpsを表示しています。

FixedUpdateメソッド内ではTime.fixedDeltaTimeとTime.deltaTimeを使用して秒数を計算しています。

FixedUpdateメソッド内でTime.deltaTimeを呼び出すと固定フレームレートの値が返されるようなのでその為の実験です。

固定フレームレートの値という事はTime.fixedDeltaTimeの値が返されるという事でしょうか。

今回はTimeManagerのFixed TimeStepを0.02のまま使用します。

それではこのスクリプトを何らかのゲームオブジェクトに設定しUnityを実行してみましょう。

UpdateとFixedUpdateのテスト1

↑が実行最初の結果です。

FixedUpdateは50fpsで呼ばれているのがわかりますね。

Updateも50fpsになってます。

UpdateとFixedUpdateのテスト2

↑がしばらく実行した後の結果です。

FixedUpdateではほぼ50fps、Updateでは60近くになっています。

Updateメソッドは毎フレーム実行されるのでこういう風になりますね。

ゲームのフレームレートはスタンドアロン(パソコンの実行形式)では最大達成可能フレームレート、スマフォ等のモバイル出力された場合は最大達成可能フレームレートより小さくなっています。

このフレームレートはスクリプトから設定する事が可能です。

先ほどのスクリプトにも記述していていましたが、Application.targetFrameRateに値を入れる事で変更する事が可能です。

ここらのフレームレートに関しては

Application-targetFrameRate - Unity スクリプトリファレンス
Specifies the frame rate at which Unity tries to render your game.

Unityのスクリプトリファレンスに記述されていますが、Quality Settingsの設定によっては無視されます。

QualitySettingsを開く

↑のようにUnityメニューのEdit→Project Settings→Qualityを選択します。

QualitySettingsのインスペクタ

Quality SettingsのインスペクタでV Sync CountがDon’t Syncの時はスクリプトで設定されたフレームレートが適用されます。

それ以外の場合は無視されると言う事ですね。

それではSync Countの設定をDon’t Syncにして確認してみましょう。

フレームレートを変更した実験

スクリプトでフレームレートを20に設定したのでUpdateのfpsが20付近で止まっています。

UpdateとFixedUpdateでの入力値の取得について

UpdateメソッドとFixedUpdateメソッドの違いについてわかったところで次のようなスクリプトをMainCamera等に取り付けます。

Unityを実行してSpaceキーを押しっぱなしにすると以下のようになります。

UpdateとFixedUpdateでの入力値の取得の結果

UpdateとFixedUpdateではSpaceキーを押したらコンソールにログを出力するという同じ処理をしていますが、実際に出力される回数はUpdateメソッドの方が多くなります。

これはFixedUpdateメソッドはデフォルトでは0.02秒に1回実行されるのでその間はスペースキーを押しても入力されたかどうかの判断をする処理が実行されていない為、押していても入力の判定がされていない為です。

なのでRigidbodyを使った移動等を行う場合はUpdateメソッドで入力値の計算をし、FixedUpdateメソッドで移動の処理を行う方が入力値の取得漏れが少なくなるかもしれません。

キャラクターの移動等ではあまり支障はでなそうですが、ジャンプボタンを押した時にジャンプをさせる時に『押したのにジャンプしない!!』という状況が発生します。

今回はInputManagerを使っていますが、新しい入力システムのInputSystemを使った場合は入力がされた時にイベントが実行されるようにしておくとよりわかりやすいかもしれません。

Unityの新しい入力システムInputSystemを使ってみる
UnityのInputManagerに変わる新しい入力システムInputSystemの使い方とInputSystemを使ったサンプルを作成してみます。

上の記事の「BehaviourをSend Messagesにして取得」の項目を参照してください。

終わりに

UpdateメソッドとFixedUpdateメソッドの違いはなんとなく理解してましたが、こうやって見ていくと呼ばれるタイミング自体が違うというのが再認識されました。

キャラクターを動かす場合CharacterControllerとRigidbody+コライダの2つのやり方がありますが、

CharacterControllerの場合はUpdateで操作、Rigidbody+コライダの場合はFixedUpdateで操作した方がいい理由がなんとなくわかりますね。

Rigidbodyの場合物理的な挙動(相手方に力を与えたり逆に力を加えられたり)を扱っているのでタイミングとしてはFixedUpdate内で記述した方がいいってことですね。

ふむふむなるほど・・・・・(-_-)

本当にわかっているかどうかはまぁ置いておいて・・・・(^_^;)

なんとなくでも違いがわかったのは良かったと思います。

ふむふむなるほど・・・・・(-_-)

タイトルとURLをコピーしました