はじめに
UnityでComponentを作成していると、実行順を制御したい場合が出てきます。
例えばComponentAでインスタンスを作成し、ComponentBでそれを参照したいときなどにはComponentAの実行後にComponentBを実行しないとnull参照が発生します。
Updateでインスタンスが作成されるまで毎回参照をチェックする方法や、AwakeとStartを使い分ける方法などもありますが、Updateで毎回やるのは非効率ですし、Startはオブジェクトが有効でないと呼ばれないなど、地味に不便な場合があります。
このような場合があるので、Componentの実行順を制御できる方法を知っておくと便利です。
実行順を指定すると、StartやAwake、Updateなどの各メソッドが呼ばれるタイミングをコンポーネントごとに制御することができます。
Project Settingから設定する
1つ目の方法はProjectSettingからExecutionOrderを設定する方法です。
Edit > ProjectSettings > Script Execution Orderという項目からMonoBehaviourを継承したコンポーネントの実行順序を指定することができます。
デフォルトは0でDefault Timeという中に含まれています。
右下の+ を押すと選択肢が表示されるので実行順を調整したいコンポーネントを選択します。
追加された項目は手動で値を調整するか、マウスでドラッグすることで移動できます。
ドラッグによる移動の場合値は自動で割り振られます。
値が小さいほど先に実行されます。
属性で指定する
ProjectSettingsからだとGUIで設定ができ、視覚的にもわかりやすいですが、購入したAssetをプロジェクトにインポートした時に、大量のコンポーネントが追加されて、選択肢から選ぶのがめちゃくちゃ手間になる場合があります。
そんなときには、属性を設定する方法が便利です。
下記のように「DefaultExecutionOrder」属性を指定してやると、指定した優先度でこのコンポーネントが実行されるようになります。
using UnityEngine;
[DefaultExecutionOrder(-10)] //ここでOrderを指定
public class MonoBehaviourScript01 : MonoBehaviour
{
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
Debug.Log("MonoBehaviourScript01 Start Called");
}
// Update is called once per frame
void Update()
{
}
}
何も指定していないコンポーネントは0に相当するので、マイナスを指定してやると、通常のコンポーネントはよりも先に実行してくれるようになります。
実行例
サンプルとして下記のようなScriptを用意してStartの実行順を確認してみます。
public class MonoBehaviourScript01 : MonoBehaviour
{
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
Debug.Log("MonoBehaviourScript01 Start Called");
}
// Update is called once per frame
void Update()
{
}
}
これと同じようなものを下記3つコンポーネントとして用意します。
MonoBehaviourScript01
MonoBehaviourScriptDefault
MonoBehaviourScript02
何も指定せずに実行すると下記のようになりました。
02 → Default → 01 の順で呼ばれています。
これに属性を指定し以下のようにしてみます。
using UnityEngine;
[DefaultExecutionOrder(-10)] //属性指定を追加
public class MonoBehaviourScript01 : MonoBehaviour
{
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
Debug.Log("MonoBehaviourScript01 Start Called");
}
// Update is called once per frame
void Update()
{
}
}
各コンポーネントに以下の属性を指定
コンポーネント | 優先度指定 |
---|---|
01 | -10(優先度高) |
Default | 何も指定しない |
02 | 10(優先度低) |
するとこのように実行順が変わり、指定した通りの順番でStartがコールさrていることがわかります。
さいごに
ProjectSettingsからやるほうが視覚的にはわかりやすいですが、属性指定の方がコード上で検索することもできるので、個人開発の方はコード上で指定する方が便利だと思います。
自身の状況によって使い分けていただければと思います。
最後までお読みいただきありがとうございます。
コメント