Unityエディターでプレイヤーを起動すると、ヒエラルキー上に出てくるDontDestroyOnLoadという何か。Don't Destroy(壊すな!)という文言から恐ろしい、触れちゃいけない何かなのかなと思っていたんですが、UnityのScene Management周りを勉強していて、ようやくその正体が分かりました。
要約!
↓
先にまとめてしまうと、ヒエラルキー上のDontDestroyOnLoadとはゲームを起動してから終了するまでずっと存在し続けるStaticなSceneであり、ここに存在するゲームオブジェクトは、ランタイム中のシーンのロード、アンロードの影響を受けなくなります。
DontDestroyOnLoad(Object target)は、目標のゲームオブジェクトをそこに移動させるためのメソッドです。
LoadSceneMode
Unityのシーンをロードする方法は二種類あり、Singleモードは現在のシーンを完全に削除して、新しいシーンを読み込むというものです。もう一つのAdditiveはその名の通り、追加的にシーンを読み込むモードですが、ここでは割愛します。
Singleモードで現在のシーンから新しいシーンにゲームオブジェクトを持ち込むためにDontDestroyOnLoadメソッドを使います。
ただし、厳密には新たなシーンにゲームオブジェクトが移動するのではなく、DontDestroyOnLoadシーンに移動して、ずっとそこに居続ける、という感じです。
重複に注意!
もしも、そのゲームがリニアな構造で、最初のシーンから最後のシーンまで一方通行の場合、最初のシーンでDontDestroyOnLoad処理をしてしまえば、それ以降はシーンを順に読み込んで進行していく、で問題はないはずです。
しかし、いくつものシーンを何度も行ったりきたりするようなゲームの場合、最初のシーンを再度読み込むと、またDontDestroyOnLoad処理が実行されてしまい、オブジェクトが重複してしまいます。
公式のドキュメントページではこの対応策として、タグを使って同種のオブジェクトを検索し(FindGameObjectsWithTag)、既に存在してたらDestroyする、という方法を採用しています。今回のテストで書いたスクリプトにも、これを採用しました。
こういった対応策を取らない限り、該当シーンが読み込まれる度に、DontDestroyOnLoadシーンにゲームオブジェクトが詰みあがっていくので、処理が重複したり、最悪メモリ不足でゲームが落ちる、という事態になるかもしれません。
自分が考えた対応策は、一番初めに初期化のためのシーンを読み込み、そこで必要なオブジェクト、つまりプレイヤーキャラやシステム関連などゲームを通して存在し続けるオブジェクトをDontDestroyOnLoad処理してしまって、その後、直ぐに実際のゲームコンテンツを含むシーンを読み込む、という方法です。
これだと実質一瞬で、プレイヤーにとって最初のシーンが読み込まれゲームが始まることになり、あとは初期化のためのシーンがロードされなければ、重複の危険性もない、ということになります。この手法は今度試したいと思います。
あとがき
今まさにSceneManagement周りを勉強中なのですが、かなり難しい!しかし、UnityのSceneというものに向き合っていかないとダメな時期だと思うので、なんとか乗り越えたいと思います。