sceneLoadedで詰まる

アンドロでの動作確認をいちいち実機でやるの面倒だよね。エミュレータ使えば楽になったりする?ってことで調べて

英語とか Unityで作成したアプリをAndroid Studioのエミュレータで動かす

エミュ動かせるまでにはなったけどさ、Unityでビルド&ランを実行したらビルドは瞬時に終わるんだけど、エミュへのインストールに5分以上かかってまじうざい。実機へファイル転送してからのインストするほうが時間が短いってどういうことだよ。エミュの出番ないじゃん!複数解像度試せる利点はあるから良いのか。何か設定が悪いのかしら?

エミュは一旦我慢するとして、サンプルコードに以下の関数が有りましてね

//This is called each time a scene is loaded.
void OnLevelWasLoaded(int index)
{
   //Add one to our level number.
   level++;
   //Call InitGame to initialize our level.
   InitGame();
}

OnLevelWasLoadedが非推奨になって将来廃止予定だよって警告がでるの。代替案があるんだろ?って探したらSceneManager.sceneLoadedを使えば良いらしい。あまり深く考えずに書き換えてみよう。要点抜き出すと

void Awake()
{
    SceneManager.sceneLoaded += TestSceneLoaded; 
}

void TestSceneLoaded(Scene sceneName, LoadSceneMode sceneMode)
{
    level++;
}

これで解結すると思ったらバグ発生。ローグライクでlevel1(1階層目)から始まるはずが2でスタート。次のlevelへ移動したら数値が+1ではなく+2される。なんじゃこりゃー。Awakeが複数回呼ばれてsceneLoadedへ関数2回登録したとか?調べたけどそんなことはない。Loadedがゲーム開始時に1回呼び出され、レベル変更時には二回呼び出されてる。なんで?

そもそも、Levelは1で初期化してんだよね。シーン呼び出し時に+1されるのだから、2から始まるのは当然か。最初のサンプルコードでは何故+1されず1でスタートしてんの?OnLevelWasLoadedが呼び出されてないんじゃね?調べてみると

Awake
OnEnable
OnLevelWasLoaded
Start
の順番で呼び出される。
Awake,Startはひとつのオブジェクトについて、一度しか呼ばれない。
しかし、OnEnableは、Enableされるたびに呼ばれる。

で、OnLevelWasLoadedが呼び出されてないんだがどういうことだよ。よくよく調べてみると、最初のシーンロード時はOnLevelWasLoadedが呼び出されないんだってさ。

わ か る か よ

名前見たらロード後に呼び出すとしか思わんわ。2回目からのロード時に関数が呼び出されるのなら、OnLevelWasLoadedの話は解決。次はsceneLoadedの仕様を解かねばならぬ。解説ブログをぐぐり

  1. Awake
  2. SceneManager.sceneLoaded
  3. Start

の順番で呼び出しが発生すると判明。つまり

Startでメソッドを登録すると最初のシーンでは実行されず
Awakeでメソッドを登録すると最初のシーンでも実行されます

あーなるほど、そういうことか。

わ か ら ね ぇ Yo!

結論として

void Awake()
{
    //SceneManager.sceneLoaded += TestSceneLoaded; 
}

void Start()
{
    SceneManager.sceneLoaded += TestSceneLoaded;
}

void TestSceneLoaded(Scene sceneName, LoadSceneMode sceneMode)
{
    level++;
    InitGame();
}

こう書けば良いのでした。

【Unity】OnLevelWasLoadedとSceneManager – うら干物書き

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です