Unityメンバの初期化をシーケンス図にしてみた
メンバーの初期化
シーケンス図
- .ctor(コンストラクタ)からメンバの初期化子が呼ばれる。
- コンストラクタ本体。スクリプティング API を使わない初期化はここで行える。
- Inspectorで設定している値が反映される。
- スクリプティング API が使えるのはこれ以降
- Awake() 自身に閉じている初期化は多分ここで行う。
- OnEnable() 有効・無効毎に行うことがあればここで行う。
- Start() 他のオブジェクトを参照する初期化はここで行う。
- Update()等
- OnApplicationQuit()
- OnDisable()
- OnDestroy()
ConsoleにはInitializeMember()の後にConstructor()が表示されるが、Stack Traceを見ると.ctorからInitializeMember()が呼び出されているので、シーケンス図では逆にした。順番的にはコンストラクタ―本体はInitializeMember()後に実行される。
Inspectorでmemberを100に設定しているのでシーケンス図に追加した。
Play前にすでにコンストラクタは呼ばれ、停止後もDestory後にまたコンストラクタが呼ばれている。
https://www.websequencediagrams.com/examples.htmlにアクターの書き方もあったのでアクターを入れてみた。このツール優秀だなぁ。
シーケンス図テキスト版
title Initialize
actor user
Unity->Test: Constructor() 1
Test->Test: InitializeMember()
note right of Test: Play前に初期化されている
user->Unity: Play
Unity->Test: Constructor() 1
Test->Test: InitializeMember()
Unity->Test: Inspector
Unity->Test: Awake() 100
Unity->Test: OnEnable() 101
Unity->Test: Start() 102
user->Unity: Stop
Unity->Test: OnApplicationQuit() 103
Unity->Test: OnDisable() 104
Unity->Test: OnDestroy() 105
note right of Test: また初期化される
Unity->Test: InitializeMember()
Unity->Test: Constructor() 1
試したTestクラス
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour
{
public int member = InitializeMember();
static int InitializeMember()
{
Debug.Log("Unity->Test: InitializeMember()");
return 1;
}
Test()
{
Debug.Log("Unity->Test: Constructor() " + member.ToString());
member++;
}
private void Awake()
{
Debug.Log("Unity->Test: Awake() " + member.ToString());
member++;
}
private void OnEnable()
{
Debug.Log("Unity->Test: OnEnable() " + member.ToString());
member++;
}
// Start is called before the first frame update
void Start()
{
Debug.Log("Unity->Test: Start() " + member.ToString());
member++;
}
private void OnDisable()
{
Debug.Log("Unity->Test: OnDisable() " + member.ToString());
member++;
}
private void OnDestroy()
{
Debug.Log("Unity->Test: OnDestroy() " + member.ToString());
member++;
}
private void OnApplicationQuit()
{
Debug.Log("Unity->Test: OnApplicationQuit() " + member.ToString());
member++;
}
}
GameObjectのアクティブ・非アクティブ、Scriptコンポーネントの有効・無効
InspectorでGameObjectのチェックボックスでアクティブ・非アクティブを切り替え、Test(Script)コンポーネントのチェックボックスで有効・無効を切り替えてみた。
- Scriptが無効でもGameObjectがアクティブになったときにAwakeが呼ばれる。ちょっと不思議。
- GameObjectが非アクティブのときにScriptを有効・無効にしてもOnEnable()、OnDisableは呼ばれない。
title Active/非Active, Enable/Disable
actor user
user->GameObject: 非アクティブ
user->Test(Script): 無効
user->Unity: Play
Unity->Test: Constructor() 1
Test->Test: InitializeMember()
Unity->Test: Constructor() 1
Test->Test: InitializeMember()
user->Test(Script): 有効
user->Test(Script): 無効
user->GameObject: アクティブ
Unity->Test: Awake() 100
note right of Test(Script)
初めてアクティブに
なったときに1度だけ
Awake()が呼ばれる
end note
user->Test(Script): 有効
Unity->Test: OnEnable() 101
Unity->Test: Start() 102
note right of Test(Script)
アクティブand有効では
OnEnableが呼ばれる。
1度だけStart()が呼ばれる。
end note
user->Test(Script): 無効
Unity->Test: OnDisable() 103
note right of Test(Script)
無効ではOnDisable()が呼ばれる。
end note
user->GameObject: 非アクティブ
user->Test(Script): 有効
user->GameObject: アクティブ
Unity->Test: OnEnable() 104
user->GameObject: 非アクティブ
Unity->Test: OnDisable() 105
Unity->Test: OnDestroy() 106
Unity->Test: InitializeMember()
Unity->Test: Constructor() 1
横に広がりすぎないように複数行のノートを付けてみた。
初期化を見ようと思ったのでファイナライザーとか定義してなかったな。まぁ、いいかぁ。