コガネブログ

平日更新を目標に Unity や C#、Visual Studio、ReSharper などのゲーム開発アレコレを書いていきます

【Unity】Awake や Start の実行順を意識することなく他のコンポーネントを参照する

// スコアを管理するコンポーネント
public class Score : MonoBehaviour
{
    private UILabel mUILabel;
    
    private void Awake()
    {
        mUILabel = GetComponent<UILabel>();
    }
    
    public void SetText( string text )
    {
        mUILabel.text = text;
    }
}

// ゲームを制御するコンポーネント
public class GameController : MonoBehaviour
{
    private void Awake()
    {
        var score = GetComponent<Score>();
        score.SetText( "1234" );
    }
}

例えばスコアやテキストを管理する GameController コンポーネントがあり、
GameController の Awake で Score コンポーネントを取得して
表示を変更するために SetText を呼び出した場合、

スクリプトの実行順によって Score コンポーネントの Awake よりも
GameController コンポーネントの Awake が先に呼ばれてしまうと
Score コンポーネントの mUILabel が null のままになってしまい、
null 参照の例外が発生してしまいます

なので、他のコンポーネントを参照する場合は
Awake ではなく Start に処理を書くのが安全ですが

public class Score : MonoBehaviour
{
    private UILabel mUILabel;
    
    private UILabel uiLabel
    {
        get
        {
            if ( mUILabel == null )
            {
                mUILabel = GetComponent<UILabel>();
            }
            return mUILabel
        }
    }
    
    public void SetText( string text )
    {
        uiLabel.text = text;
    }
}

このように、Awake でコンポーネントを取得するのではなく
プロパティを通して初めて呼び出された時にコンポーネントを取得するようにすると
Awake や Start の実行順を意識することなくゲーム開発できます