【Unity】Script(Component)の実行順を制御する

はじめに

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何も指定しない
0210(優先度低)

するとこのように実行順が変わり、指定した通りの順番でStartがコールさrていることがわかります。

さいごに

ProjectSettingsからやるほうが視覚的にはわかりやすいですが、属性指定の方がコード上で検索することもできるので、個人開発の方はコード上で指定する方が便利だと思います。

自身の状況によって使い分けていただければと思います。

最後までお読みいただきありがとうございます。

コメント

タイトルとURLをコピーしました