Unity フレーム

コンピューター

Unity フレーム処理

フローチャート

Unity フローチャート
フローチャート

シーン(Scene)

シーンは.unityと拡張子のついたファイルに保存されている実行時のデータ構造を保持します。UnityEngine.SceneManagement名前空間の構造体です。
Scene構造体はシーンのインデックス、名前、シーンに結び付けられたルートオブジェクト、シーンオブジェクトを管理するための各種のフラグを保持しています。

UnityEngine.SceneManagementはシーンを管理すための処理を行っておりSceneManagerクラスにはシーンの生成や破棄、シーンの各種設定などシーンを管理するためのメソッドが用意されています。

Unityのシステムがゲーム起動しシーンを読み込むと付随するScriptやゲームオブジェクトのインスタンスを生成、その後ゲームオブジェクトにスクリプトのインスタンスをアタッチします。

名前空間はクラスを管理するためのフォルダのようなものでC#によって提供されています。

検証

「インスタンス化とか意味わかんねえ」という方はこちら。オブジェクト指向におけるメモリの管理方法をまとめてあります。

オブジェクト指向言語のメモリ管理
オブジェクトプログラミングのメモリ管理 メモリの管理 ごく簡単に。 静的領域:グローバル変数、命令コード。 ヒープ領域:インスタンス、バッファ。 スタック:メソッドに渡す引数など。 静的領域 このメモリ領域は最初にプログラ...

Initialization

まずはInitialization(初期化)フェーズから見ていきます。

ここで呼び出されるのはAwake()メソッドなど初期化メソッド。以下Unityリファレンスの引用です。

スクリプトのインスタンスがロードされたときに呼び出されます
Awakeはゲームが始まる前に変数やゲーム状態を初期化するために使用します。 Awakeはスクリプトのインスタンスが生存している間、一度だけ呼び出されます。

リファレンス

とあるのでAwake()はメソッドはゲームオブジェクトにアタッチされたScriptのコンストラクタの役割をはたしているのかもしれません。

以下のコードを適当なオブジェクトに貼り付けてゲームを呼び出します。

このスクリプトを適当なオブジェクトにアタッチしてゲームモードを起動します。
Consoleを確認すると

Awake()、OnEnable()、Start()の順に表示されます。
その後はUpdate()がフレームを更新する為に呼び出されるだけです。
1度だけAwake()が先に呼び出されてその後、OnEnable()、Start()の順で呼び出されています。

今度はScriptの無効化と有効化で検証してみます。

ScriptのActiveのオンオフ

Scriptを無効化してゲームを実行します。

するとAwake()だけ呼び出されます。
その後ゲーム中にチェックを入れなおすとOnEnable()とStart()が呼ばれます。
その後はオンオフを繰り返しても実行されるのはOneEnable()だけです。

リファレンス通りAwake()はScriptのインスタンスを生成した時に呼び出されています。
OnEnable()はScriptインスタンスがゲームオブジェクトにアタッチされて実行可能になれば実行されます。

オブジェクトのActiveのオンオフ

今度はオブジェクトを無効化してみます。

Awake()もOnEnable()もStart()も実行されません。
ゲームを実行したままチェックをオンにするとAwake(),OnEnable(),Start()の順に実行されました。
もう一度チェックのオンオフを繰り返します。
その場合、OnEnable()だけ実行されます。
理由は分かりません。

Awake()はゲームオブジェクトのインスタンスが読み込まれて(それだけではだめ)且つ、アタッチされたゲームオブジェクトが有効化された最初の一回だけ呼び出されます。
Start()はScriptのインスタンスがゲームオブジェクトにアタッチされた最初の一回だけ呼び出されます。
OnEnable()はScriptが有効になる度に呼び出されます。

コンストラクタはnewされてインスタンス化された瞬間に呼び出されますが、Awake()の場合はインスタンス化されて且つそのゲームオブジェクトが有効化されsceneに紐づけられた瞬間に呼び出されます。

もう少し検証してみます。

Awake()が呼び出される順番

Editer

今度は少し飛ばしたEditerフェーズを見てみます。
フローチャートを見るとAwake()とOnEnable()のあるInitializationとStart()のあるInitializationの間にEditerというフェーズがあります。
ここで呼び出されるのはReset()メソッド。
Unityのリファレンスにはこうあります。

デフォルト値にリセットします

Reset はインスペクターのコンテキストメニューにある Reset ボタンやコンポーネントを初めて追加するときに呼び出されます。 この関数はエディターモードのみで呼び出されます。Reset はインスペクターでデフォルト値を設定するときにもっともよく使用されます。

リファレンス

とありますInspectorでコンポーネントをアタッチした時やリセットした時エディットモードのみで実行されるようです。
以下のScriptを適当なオブジェクトに貼り付けて実験してみます。

publicのテスト変数に0を格納し、Reset()メソッドでその値を設定するだけのコードです。


Editモードはこの再生ボタンが押されていない状態で、Playモードはここを押して青くなった状態です。

Editモードで適当なオブジェクトにこのScriptをアタッチしてみます。

コンソールを確認するとScriptをアタッチした瞬間にログが表示されます。
今度はScriptの横にある歯車をクリックしてResetをクリックしてみます。
するとログにしっかり表示しされます。

PlayモードでオブジェクトにScriptをアタッチしてます。
今度はコンソールにログは表示されません。
Rsetボタンを押してみても何も表示されません。

このことからも分かるようにゲームを実際にプレイしているときには使われないメソッドです。
Editモードでコンポーネントの数値を初期化したいときに使えます。
例えばTransformの位置情報だとかその辺ですね。

Physicsフェーズ

フローチャートで見ると最初に呼び出されるのはFixedUpdate()メソッドですね。

MonoBehaviour が有効の場合、この関数は毎回、固定フレームレートで呼び出されます。

Rigidbody を扱う時に Update の代わりに FixedUpdate を使用します。 例えば Rigidbody に力を加える場合、 Update ではなく、毎フレームごとの FixedUpdate の中で力を適用する必要があります。

リファレンス

つまりゲーム内の物理的な影響を演算する直前に呼び出されるメソッドです。
RigidBodyをアタッチしたオブジェクトをRigidBodyに用意された機能で動かす場合はここで設定します。
ここで設定した情報を元に物理演算を開始します。

FixedUpdate()はデフォルトでは0.02秒間隔で呼び出されます。
間隔の変更はEdit→Project Settings→Time→TimeManagerでできます。

一定間隔で呼ばれるのは衝突判定など物理的な挙動を元にゲームオブジェクトのTransformを変更する可能性があるからですかね。

Update

Time.deltaTime

前回のフレームが呼びされた時間と現在のフレームが呼び出された時間の差が保存されています。
フレームとフレームの間隔ですね。
フレーム間の処理数が多いと遅延し間隔が伸びていきます。

コメント