【Unityゲーム制作】AwakeとStartとOnEnableの違いと順番を徹底解説!

Creating Game

こんにちは。あっきーです。
早稲田大学を退学して4年間アメリカ留学に行く予定のもので、ゲーム制作をしています。

Unity初心者
Unityでスクリプト書いているけど、StartやAwake、そしてOnEnableの違いや呼び出しの順番とかよくわからないなぁ。どう使い分けるんだろ?

今回はこれを解決していきます。

特にStartとAwakeの違いはよくわかりませんし、ぶっちゃけどっちも一緒じゃんと思うところもありますよね。
しかし、明確に違うポイントはありますし、うまく使い分けることで動かすプログラムの幅も広くなります。

しっかりこのポイントを押させてゲーム制作を楽しみましょう。

Awake, Start, OnEnableの意味は?

まず、この3つのメソッドの役割について解説していきます。

  • Awake:オブジェクトのインスタンス化直後に、最初に1度だけ実行
  • Start:スクリプトアクティブ時に、Updateの前に1度だけ実行
  • OnEnable:オブジェクトがアクティブになるごとに1度だけ実行

まとめるとこのようになっています。これだけ見ても分からないと思うので詳しく説明していきます。

Awakeは一番初めに呼び出される

Awakeはざっくり言うとどのスクリプトよりも一番初めに呼び出されるメソッドです。
多くはStartを使って一番最初の処理を書いているかと思いますが、そのStartよりも早く呼び出すことができます。

ただ、単純に一番最初に呼び出されるというわけでも無くて、以下のような特徴があります。

  • オブジェクトが非アクティブの場合は呼び出されない
  • スクリプトが非アクティブでも呼び出される

また、Startの場合は、オブジェクトが非アクティブの場合はもちろん、スクリプトが非アクティブの場合も呼び出されることはありません。

AwakeとStartの違いを確認してみる

では、実際にAwakeとStartの違いを見てみましょう。
以下のようなスクリプトを用意しました。


using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class NewBehaviourScript : MonoBehaviour
{

    void Awake()
    {
        Debug.Log("Awakeが呼び出されました");
    }
    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("Startが呼び出されました");
    }
}

Awakeが呼び出されたら「Awakeが呼び出されました」と、Startが呼び出されたら「Startが呼び出されました」とコンソール上に出力するものです。

そしたら図のように、何かしらオブジェクト(ここではCube)を生成して先ほどのスクリプトをつけます。

この状態で、ゲーム実行してみましょう。

上から順々に表示されるので、AwakeがStartより早く呼び出されているのが分かりますね。

今度は、このオブジェクトを非アクティブにして実行してみましょう。


オブジェクトを名前の左にあるチェックを外して非アクティブにします。そして実行すると。。。


何も表示されてないので、呼び出されていないということが分かりますね。
この状態でオブジェクトをアクティブにすると、コンソールにメッセージが表示されます。

今度は、オブジェクトはアクティブにして、スクリプトを非アクティブにしましょう。


このようにスクリプトのチェックを外して実行すると


Awakeだけ呼び出されていますね。StartとAwakeにはこのような違いがあります。

AwakeもStartも1度だけ呼び出される

よくある勘違いとして、「AwakeとStartはアクティブになるごとに何度も呼び出される」というのがあります。
しかし、AwakeもStartも1度呼び出されたら、それ以降呼び出されません。
なので、一定時間ごとに初期化をしたいという場合は別で初期化するメソッドを設定する必要があります。

OnEnableとは?

一方OnEnableはどんなメソッドかというと、アクティブになる毎に呼び出されるものです。
これも確認してみます。

先ほどのスクリプトに次のようなコードを追加します。


    void OnEnable()
    {
         Debug.Log("OnEnableが呼び出されました");
    }

オブジェクトをアクティブの状態にして実行してみます。


もちろん、アクティブの状態なので呼び出されていますが、このままオブジェクトのチェックをつけたり外したりしてみてください。


すると、このようにOnEnableだけアクティブになるごとに呼び出されていますね。
これがOnEnableの特徴です。

Awake, Start, OnEnableの順序は

さっきの実行結果でお気づきかもしれません。

実は、これら3つのメソッドは順序が「Awake→OnEnable→Start」となっているんですね。
「AwakeはStartの前に呼び出される」と知っていたかもしれませんが、OnEnableもStartより早く呼び出されるんですね。
データが取得できないなどのエラーが起こってしまうことがあるので気を付けましょう。

AwakeやStart, OnEnableの使い方は?

最後に、これら3つのメソッドの使い方についてお話します。

基本はどれも初期化(初期設定)に使う

これらはどれも「はじめに実行される」という点から、初期化に使います。
「キャラクターのHP設定」、「キャラクターの最初の位置設定」、「コンポーネントの取得」などによく使われますね。

Awakeでの値取得には注意

一つ注意点としては、Awakeでの値取得です。
例えば「スクリプトAのAwakeでスクリプトBのAwakeで設定した値を取得する」みたいなプログラムを書くとします。

すると、スクリプトBでのAwake処理が終わってない状態でスクリプトAで取得しようとしてエラーが起こってしまう可能性があります。(Start同士でも同様)


これは、Startで取得をすると避けることができます。(というか、このエラーを避けるためにAwakeとStartが区別されているんだと思う。)

ちなみに、コンポーネントの取得などはAwakeで行っても問題ありません。コンポーネントはオブジェクトにすでについているものなので、最初から取得できるからです。
とはいえ、ほとんどはStartで初期化をしますね。

OnEnableは非アクティブなオブジェクトの取得に有効

一方OnEnableはというと、非アクティブなオブジェクトの取得に使えます。

「ある名前のゲームオブジェクトを取得したい」場合、GameObject.Find(“名前”)というのが使えます。

例として以下のSampleAというスクリプトを作ります。そして、これを今まで使ってきたCubeに付けます。


using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SampleA : MonoBehaviour
{
    private GameObject g;

    void Start()
    {
        g = GameObject.Find("Sample");
        Debug.Log(g);
    }
}

また、新しくCubeを作って、名前をSampleにして非アクティブにしましょう。


この状態で実行してみてください。


このように、Nullが返ってきました(Nullは「何もない」という意味です)。このように、非アクティブでは取得できないデータもあります。

これをOnEnableを使えば「アクティブになったときに取得」できるので、エラーが起こらなくなります。

リストアップなどに使える

OnEnableに関してですが、RPGなどで「アイテムリスト」とかよくありますよね。

あれって「メニューが画面を開いたときだけアイテムを表示する」というわけですよね。
これも「メニュー画面が開いた」というアクティブなときに実行したいわけですから、OnEnableが大活躍するというわけです。

やりながら覚えていきましょう

というわけで、Awake, Start, OnEnableの意味と順序、そして使い方をお話しました。
といってもこれを読んだだけで理解できるとは思っていません。実際に作ってみてやっとわかることだと思います(プログラミングってそういうもん)。

なので、ちょっとずつ作りながら慣れていきましょう。

それでは、また。

人気記事現役大学生が告白!大学生がブログを始めるのをオススメする理由

人気記事WordPress(ワードプレス)の始め方【初心者でも15分で開設】