今日は完全にプログラミングの話をしたいと思います。
特に「Unity」に関するプログラミングの話。
「Unityでは、初期化は”Awake”を使ってしなさい」。
ということが、いろんな記事や本で書かれていると思います。
じゃあ、それがなぜなのか、なぜコンストラクタは使えないのかまで理解したい と思い、いろいろ調べたのでここにまとめます。
まず、コンストラクタを使ってはいけない(使えない)のは、MonoBehaviourを継承しているクラスだけです。
つまり、コンポーネントとして使われるクラスにおいて、コンストラクタが使えないのです。
まず、これらのクラスが実体化するというのは、シーンのあるオブジェクトにくっつくというイメージです。
これらが実体化される場面を、あえて分けてみると、
①シーン上で初めから配置されているオブジェクトにそのコンポーネントが加えられており、そのシーンが読み込まれたときに実体化する。
②AddComponent によって、追加されたときに実体化する。
③アセットのあるプレハブに加えられており、そのプレハブがInstantiateで実体化した時、一緒に実体化される。
などになりますね。
で、これらに共通するのは、すべてUnityのエンジン側(っていうかな?)から呼び出されていると思います。当然、Unity側が自分の作ったクラスのコンストラクタにはどんな引数を与えればよいかを知っているはずがないため、Unity側からしたら「コンストラクタは作らないでね!」という気持ちなんです。だから、コンストラクタはそもそも作ってはいけないようになっているということだと思います。
*フィールドで” float speed = 20; ”のようにして初期化すること(変数初期化子による初期化)ができるので、主にそれで初期化をするとよいでしょう。
*また、クラスの中にクラスを宣言することができますが、そのクラスはコンストラクタによる初期化ができます。だから、クラス内でクラスを宣言して、そのクラスをインスタンス化し、メンバとして扱うということができます。
*尚、フィールドで” int x ; ”のように、初期化子無しで宣言した場合、デフォルト値で初期化されます(整数なら 0 、参照型なら null とかです)。
コンストラクタで本来やることは、フィールドの初期化だけとは限らないでしょう。
たとえば、実体化したときに文字を表示させるだとか。
そういう処理を、Unityでは、
Awake関数 ないし、 Start関数 に書きなさい
ということです。
*尚、それぞれ微妙に違うので注意が必要です。また、OnEnableとかUpdataなど他にもいろいろUnity側から呼び出される関数が沢山あります。これらは、イベント関数 というそうです。
まとめると、
・MonoBehaviourを継承しているクラスでは、コンストラクタを宣言してはいけない(Unity側が困るから)。
だから・・・
↓↓
・フィールドの初期化は” float speed = 20; ”のようにして初期化する(変数初期化子による初期化)。
*尚、この記事では触れなかったが、個々で違った値を持たせたい時、インスペクタビューに表示させ、そこで上書きするように初期化することもできる。言い換えると、シーン上での実体化される自作のコンポーネントに対して、Unity側に「こう初期化して!」と依頼し、個々のコンポーネントに違いを持たせることができるということ。実はこれがUnityのすごいとこです。もちろん、他の方法で、、、たとえば、監督オブジェクトの様なものを用意して、そいつに動的に値を変化させるようにすることもできるが、手動で簡単にできるインスペクタビューからの変更はめちゃ便利です。
・それ以外の初期化的な処理は、
Awake関数 ないし、 Start関数 で行う。
(他、MonoBehaviourを継承することによって得られるいくつかの恩恵については以下のサイト様でまとめられてます。)
Unityの核であるMonoBehaviourについて - Ideals and Reality