(:3[kanのメモ帳]

個人ゲーム開発者kan.kikuchiのメモ的技術ブログ。月木更新でUnity関連がメイン。

特定のシーンでだけ破棄されないオブジェクトの実装【Unity】


このエントリーをはてなブックマークに追加

この記事でのバージョン
Unity 5.6.0f3


はじめに

Unityではシーン遷移時にシーン上のGameObjectは全て破棄されてしまいます。

なので、破棄したくない物にはDontDestroyOnLoadを実行して、永遠に破棄されないようにします。

DontDestroyOnLoad(gameObject);

f:id:kan_kikuchi:20170507170530j:plain


ただ、このやり方だとDontDestroyOnLoadしたオブジェクトは自動では永遠に破棄されないので、

特定のシーンでだけ破棄されないようにするにはひと工夫必要です。


という事で今回は、特定のシーンでだけ破棄されないオブジェクトの実装方法をご紹介!

イメージとしては以下のような感じ。


f:id:kan_kikuchi:20170520061817g:plain


Hieararchyを見るとシーンを移動する度に

不要なGameObjectが破棄されているのが分かるかと思います。


DontDestroyObjectManager

早速ですが、特定のシーンでだけ破棄されないオブジェクトを管理するクラス

DontDestroyObjectManagerのプログラムです。



なお、DontDestroyObjectManagerを使うには

CanvasFaderと、

SingletonMonoBehaviourと、

SceneNavigator

必要になります。これらについて詳しく知りたい方は以下の記事をどうぞ。




上記4つのスクリプトを作成し、適当なGameObjectに

SceneNavigatorとDontDestroyObjectManagerをそれぞれアタッチすると設定完了です。


f:id:kan_kikuchi:20170520053555p:plain
f:id:kan_kikuchi:20170516060550g:plain
f:id:kan_kikuchi:20170520053609p:plain


ここで注意が必要なのが、DontDestroyObjectManagerは複数配置するとエラーが出る事です。

最初のシーンにだけ配置する、または作成するプログラムを一度だけ実行するようにしましょう。

もしくは以下の方法を併用すると良いかもしれません。





使い方

使い方は、特定のシーンでだけ破棄したくないオブジェクトを

DontDestroyObjectManagerのSetメソッドを使って設定するだけ。


Setは以下のようにSet(オブジェクト, シーン名1, シーン名2, …)という形式で実行します。

シーン名は単体で複数でもいいですし、Listや配列で設定する事も可能です。

//Title以外に行ったらgameObjectを破棄するように設定
DontDestroyObjectManager.Instance.Set(gameObject, "Title");


//GameかResult以外に行ったらgameObjectを破棄するように設定
DontDestroyObjectManager.Instance.Set(gameObject, "Game", "Result");


//TitleかResult以外に行ったらgameObjectを破棄するように設定
List<string> sceneNameList = new List<string>(){"Title", "Result"};
DontDestroyObjectManager.Instance.Set(gameObject, sceneNameList);


//TitleかGameかResult以外に行ったらgameObjectを破棄するように設定
string[] sceneNameArray = new string[]{"Title",  "Game", "Result"};
DontDestroyObjectManager.Instance.Set(gameObject, sceneNameArray);


これで最初のイメージのような実装が出来るようになります。

なお、分かりやすいように有効なシーン名をオブジェクト名にしています。


f:id:kan_kikuchi:20170520061817g:plain


上記のイメージを見て分かる通り、DontDestroyObjectManagerに

設定したオブジェクトはDontDestroyObjectManagerの子になるので注意が必要です。


実装方法

実装方法は、SceneNavigatorを使ってシーン移動前を検知し、

その時に不要なオブジェクトを破棄するようにしているだけだったりします。


SceneManagerのsceneLoadedを使えば似たような実装は可能なのですが、



sceneLoadedはシーンが読み込まれた後に実行されるので、SceneNavigatorを使いました。


おわりに

今回の方法を使えば、同じシーンを繰り返す時や複数シーンで共通のオブジェクトがある場合

何度も作り直さずに済むようになります。


なお、シーン名は定数にした方が何かと便利だと思います。