Unityでシーンを移動した時のデータやゲームオブジェクトの引き継ぎ

今回はUnityでシーン移動時のデータやゲームオブジェクトの引き継ぎ方法を考えます。

通常であればシーン移動をする時にゲームオブジェクト等は引き継がれません。

変数の値を次のシーンでも使いたい時はスクリプトのフィールド等をstaticにしておけばシーン移動後もその値を使用する事が出来ます。

実際に試して確認してみます。

シーン間のデータの引継ぎはScriptableObjectを使った方法もあります。

UnityのScriptableObjectを使ったシーン間のデータ共有
UnityのScriptableObjectを使ってシーンを移動した時にデータを共有出来るようにします。
スポンサーリンク

シーン移動時にゲームオブジェクトとデータを引き渡す

まずはタイトル画面からゲーム画面にシーンが移動するとします。

タイトル画面シーンをSceneDataStartScene、ゲーム画面シーンをSceneDataGameSceneとして作成し、UnityメニューのFile→Build Settings…で設定しておきます。

簡単なシーン間のデータ共有

タイトル画面のシーンにGameSystemというゲームオブジェクトを作成し、Add Componentで新しいスクリプトGameStartを設定します。

staticでgameData1というint型のフィールドを宣言し、50を入れておきます。

static1

上がサンプルのタイトルシーン(SceneDataStartScene)でスタートボタンを押すとOnClickGameStartメソッドを呼び出し、ゲームシーン(SceneDataGameScene)に移動するようにしておきます。

ゲームシーンに移動するとGameSystemオブジェクトは引き継がれません。

ゲームシーンに配置しているゲームオブジェクト(どれでもOK)にGetStaticDataというスクリプトを作成し取りつけます。

GameStartのgameData1を表示させようとしています。

static2

実際に実行するとちゃんと50がConsoleに出力されました。

データの引き継ぎが出来る事はわかりましたが、ゲームオブジェクト自身が引き継がれていないのに、データだけ引き継がれているというちょっと不可思議な状態になってしまいます。

これはstaticなフィールドやプロパティ、メソッドはインスタンス化しなくても

クラス名.フィールド
クラス名.メソッド

でアクセス出来るからです。

staticが付いたものは静的メンバーと呼ばれます。

Mathf.RandomやVector3.zero等がそうですね。

その為、シーンをまたいだデータを使いたい時は

ScriptableObjectを継承する形でクラスを作成(ゲームオブジェクトに取り付けない為)し、シーン間でずっと使いたいデータをstaticで定義します。

のように使用する事が出来ます。

ただ、なんでもかんでもstaticでデータを保持するとどこからでもデータにアクセス出来てしまう為、使い道はよく考えた方がいいかもしれません。

ゲームオブジェクトを次のシーンに残す

主人公をシーンをまたいで残したい、その他オブジェクトも次のシーンで使いたい場合もあると思います。

次のシーンは新しく主人公やその他オブジェクトを配置するという事も出来ますが、かなり面倒です。

そこでシーンをまたいでゲームオブジェクトを残す機能を追加します。

GameStartスクリプトに上のように記述します。

DontDestroyOnLoadは引数にゲームオブジェクトを指定すれば、そのゲームオブジェクトがシーンを移動する時に破棄されず、次のシーンにも登場するようになります。

タイトル画面シーンに存在しているゲームオブジェクト

上がタイトルシーンに配置されているゲームオブジェクトです。

GameSystemにはGameStartスクリプトを設定し、GameStartではゲームオブジェクトを次のシーンに残す処理が記述されています。

それではタイトルシーンのスタートボタンを押して、ゲームシーンに移動してみます。

GameSystemゲームオブジェクトが次のシーンに残った

↑のように元々カメラとライトしか設置していないシーンですが、タイトルシーンからゲームシーンに移動してもGameSystemオブジェクトが残るようになりました。

ゲームオブジェクトの引き渡しをする事が出来るようになりました。

シーンを移動した時に主人公等はステータス状態もあるのでそのまま引き継げるのは楽になりますね!

ゲームシーンだけで確認する為に

シーンをまたいでゲームオブジェクト、スクリプトを残す事は出来ましたが、

このままだと最初のシーンから始めないとゲームシーンのテストプレイが出来なくなってしまいます。

なぜなら次のシーンを開いてテストプレイしようと思ったら最初のシーンから引き継いで使う事になっているゲームオブジェクトとスクリプトが存在しないからです。

これでは困るのでその対処をしましょう。

ここら辺の処理は

Persistence: Saving and Loading Data - Unity Learn
Do you want to know how to keep your data between scenes? How about between executions of your game? This recorded live session demonstrates how to do both. We ...

Unityのライブトレーニングを参考にさせて頂きました。

まずはSceneDataGameSceneにSceneDataStartSceneに作ったGameSystemゲームオブジェクトをCtrl+Cでコピーし、貼り付けます。

SceneDataGameSceneにGameSystemをコピーする

↑のようにSceneDataGameSceneにもGameStartスクリプトを取り付けたGameSystemゲームオブジェクトがあるのでゲームシーンだけでテストプレイをする事が出来ます。

GameStartスクリプトを変更します。

GameStartスクリプトにstaticなGameStartスクリプトを設定するsingletonフィールドを作成します。

Awakeメソッドでsingletonが設定されていなければ、このゲームオブジェクトを次のシーンに残し、singletonに自身のスクリプト(GameStart)を設定します。

singletonがすでに設定されている場合はすでにタイトルシーンでGameStartスクリプトがsingletonに設定されているので、ゲームシーンのゲームオブジェクトを削除します。

else以降に行くのはゲームシーンのGameSystemゲームオブジェクトに設定されたGameStartスクリプトのAwakeが呼ばれた時になりますね。

データの引き継ぎが出来るかどうか確認する為、OnClickGameStartメソッドでstaticなデータとprivateなデータにアクセスし値を書き換えます。

値を書き換えたデータはゲームシーンで取り付けたGetStaticDataスクリプトで確認する事にします。

後は確認してみましょう。

タイトルシーンからゲームシーンへと遷移させるとコンソールには

GameStart.gameData1は3
GameStart.singleton.GetGameData3()は5
GameStart.singleton.GetGameData4(1)は50

と表示され、データの引継ぎが出来ているのを確認出来ます。

ゲームシーンから開き実行するとデータを書き換えていないので

GameStart.gameData1は50
GameStart.singleton.GetGameData3()は10
GameStart.singleton.GetGameData4(1)は1

が表示されます。

ゲームオブジェクトとデータの引き継ぎの両方が出来ている事が確認出来ました。

タイトルとURLをコピーしました