まずは普通に
Base クラスから派生する Derived1, Derived2, Derived3 と、派生しない Class4, Class5 を以下のようにヒエラルキーに置いてみます。
Start関数内で自分のクラス名を表示する処理を書いて実行すると、以下のように表示されます。
実行順を指定しない場合はコール順が不定になります。
これはUnityのマニュアルにも記載のある通り、規定の動作です。
Orderを指定する
Script Execution Orderで、
Derived1>Derived2>Derived3>Class4>Class5
の順に実行するように設定します。
実行すると、意図通りの表示となりました。
次は、
Class4>Derived1>Derived2>Derived3>Class5
の順に実行するように設定します。
実行すると、意図通りの表示となりました。
ここまでは問題ありません。
基底クラスに設定するとどうなるか
Class4とClass5の間に、Baseクラスを継承したクラス全てをコールするようにしたい場合、Baseクラスに指定すれば良いように思えます。
例えば以下のような設定をしてみます。
すると以下のような表示になりました。
残念ながら、Script Execution Orderに基底クラスを指定しても、そこから派生したクラスには実行順の設定が反映されません。
Script Execution Orderではなく、スクリプトに直に実行順を書いてみます。
実行してみると、不安定な結果となりました。
継承されたクラスの実行順を操作したい場合、必ず派生先のクラスを指定する必要がありそうです。
マルチシーンの場合
Derived1~3とClass4~5を別々のシーンに分けてみます。
実行順は元に戻しておきます。
実行してみると、以下のように表示されます。意図通りですね。
しかしここには罠があります。
Test2シーンをアクティブにして、再度実行してみます。
実行すると、以下のように表示されます。
Class4~5とDerived1~3の実行順が入れ替わってしまいました。
Script Execution Orderは同一シーンの中での実行順を操作するもので、シーンを跨いだ実行順の操作はできないようです。
Test1に最優先で実行して欲しいスクリプトがあったとしても、Test2に置かれているスクリプトより前に実行することは出来ない、ということになります。
この時、Awakeはどのタイミングで呼ばれているのでしょうか。
AwakeとStart、それぞれのタイミングでログを出力するようにしてみます。
AwakeとStartはシーンとは関係なく、別々のレイヤーで呼ばれていることが分かります。
例えばTest1に初期化が必要なオブジェクトがあった場合、Awakeで初期化しておけば、Test2ではStartから使えるようになります。
まとめ
- 基底クラスにScript Execution Orderは効かない
- スクリプトの実行順はシーンごとに制御され、シーンを跨いでくれない