UnityでAwakeでAwakeする時のお話

Unity
PexelsによるPixabayからの画像

Unity では コンポーネントの間で Awake()Start() などの呼び出し順序が保証されていません.そのため次のような問題が発生します.

例として,class A はメンバクラスとして class B を持ち,class B はメンバクラスとして class C を持っているとします.クラスの構造を簡単に表すと次のようになります.

A
└ B
  └ C

そして,各クラスは次のように定義されているとします.

class A : MonoBehaviour{
  B m_b;
  void Awake(){
    var m_b = GetComponent<B>() as B;
  }
  void Start(){
    m_b.Hello();
    // do somethings
  }
}
class B : MonoBehaviour{
  C m_c;
  void Awake(){
    var m_c = GetComponent<C>() as C;
  }
  public void Hello(){
    m_c.Hello();
    // do somethings
  }
}
class C : MonoBehaviour{
  String m_str;
  void Start(){
    m_str = "Hello World!";
  }
  public void Hello(){
    Debug.Log(m_str);
  }
}

ここで,A::Start() で表示されるものが何かということが問題になります.考えられるのは次の2つです.

  • C::Start()A::Start() よりも先に実行された場合 : "Hello World!"
  • C::Start()A::Start() よりも後に実行された場合 : "" (コンパイラによっては null エラー)

対処法は次のものが考えられます.

  • m_str = "Hello World!";C::Awake() で実行する.
  • C::Hello() を呼び出す時に C::Start() が呼び出されているかチェックする.つまり,次のように C を設定します.
class C : MonoBehaviour{
  String m_str;
  bool m_isStarted = false;
  void Start(){
    m_str = "Hello World!";
    m_isStarted = true;
  }
  public void Hello(){
    if(!m_isStarted){
      Start();
    }
    Debug.Log(m_str);
  }
}

コメント