UnityのScriptableObjectを使ったシーン間のデータ共有

今回は、UnityのScriptableObjectを使って、シーンを移動した時もデータを使えるようにしたいと思います。

ScriptableObjectについては

UnityのScriptableObjectを使うと、メモリの節約が出来たり、シーン間の移動でデータを共有するのが簡単になります。この記事では基本だけを記述しています。

でやりました。

↑の記事で作成したMyDataスクリプトのファイルであるData.assetを使用しますので、あらかじめ作成しておいてください。

スポンサーリンク

シーン間の移動

まずはシーンをMain、First、Second、Thirdという名前で4つ作成します。

First、Second、Thirdシーンをボタンを押す事によって、相互に移動出来るような機能を作成していきます。

MainシーンはFirstシーンをロードするだけのシーンです。

その他のシーンは相互にボタンを押して移動出来るようにし、シーン間の移動の際はフェードイン、フェードアウトをして移動します。

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

Unity is the ultimate game development platform. Use Unity to build high-quality 3D and 2D games, deploy them across mobile, desktop, VR/AR, consoles or the Web...

シーン間のデータの移動でScriptableObjectを使いますが、今回のようにメインとなるシーンに別のシーンを追加して実行しないで、

今再生しているシーンを破棄して、次のシーンを読み込むようにしても実装出来ましたが、一応、参考サイトの流れに沿ってみました。

Mainシーン

Mainシーンの中身を作成していきます。

Mainシーンには空のゲームオブジェクトを作成し、名前をManagementとします。

Managementには新しくLoadSceneスクリプトを作り取り付けます。

ManagementにLoadSceneスクリプトを設定

↑のように設定します。

Mainシーンにはヒエラルキー上で右クリック→UI→EventSystemを取り付けておきます。

他のシーンでUIのボタンを設置しますが、他のシーンのEventSystemは削除します。

これは、現在のシーンにEventSystemが存在した時に、次のシーンを読み込んで、そのシーンにもEventSystemがあるとエラーが発生する為です。

その為、あらかじめMainシーンにEventSystemを取り付けておき、他のシーンとの競合を避けます。

LoadSceneスクリプトに処理を記述します。

Startメソッドですぐにコルーチンを開始し、LoadNewSceneメソッドを実行しています。

コルーチンに関しては

Unityでコルーチンを使うと定期的に何らかの処理を行える事が出来るようになります。一見解り辛いけど使い方がわかれば便利かも!?

を参照してください。

コルーチンは非同期処理をしてくれるものです。

LoadNewSceneメソッドでは非同期に引数で受け取ったシーンを読み込んでいます。

先ほど紹介したライブトレーニング内では、AsyncOperationの変数に入れてその後isDoneで読み込みが終わったかどうか確認するのではなく、

という感じで書いていたので、こちらでもいけるのかもしれません。

First、Second、Thirdシーン

SecondとThirdシーンはFirstシーンをコピーして設定を変えるだけなのでFirstシーンだけ解説したいと思います。

サンプルのUIを作成

まずはヒエラルキー上で右クリック→UI→Canvasを選択します。

Canvasの子要素にUI→Textを作成し、名前をSceneTitleとし、Text内に「シーン1」と記述します。

Canvasの子要素にUI→Textを作成し、名前をDataTextとします。

Canvasの子要素にUI→Buttonを作成し、名前をChangeDataとし、ChangeDataの子要素のText内に「データを書き換える」と記述します。

Canvasの子要素に空のゲームオブジェクトを作成し、名前をButtonとします。

ButtonPanelの子要素にUI→Buttonで2つのボタンを作成し、名前をSecondSceneButton、ThirdSceneButtonとします。

この名前はわかりやすいように遷移先のボタン名を入れています。

SecondSceneButtonの子要素のTextには「シーン2を読み込む」、ThirdSceneButtonの子要素のTextには「シーン3を読み込む」を入力します。

Canvasの子要素にUI→Imageを作成します。

このImageはシーン移動時のフェード用のイメージでアルファ値(透明度)を変更してフェードイン、フェードアウトを実現します。

Imageは他のUI要素も隠す必要があるので、Canvasの一番下に移動させ、UIの中で一番手前に表示されるようにしておきます。

またImageは一番手前にUI全体を覆うように配置しているので、後ろにあるボタン等が押せなくなってしまいます。

そこで、ImageのRaycast Targetのチェックを外しておきます。

Raycast Targetのチェックを外す

チェックを外すとImageはマウスクリック等の反応から無視されるようになります。

またImageのColorをクリックし、RGBを0、Aを255に設定します。

フェード用のImageのアルファを255にする

するとカメラに映る映像は真っ暗になります。

最初は真っ暗な画面

シーンが始まる時は真っ暗な状態なので、Second、Thirdシーンのフェード用のImageも同じように設定します。

出来た階層が、

Firstシーンのヒエラルキー

↑のようになります。

配置を調整して、

FirstシーンのUIの実際の配置

↑のようにしました。

シーン移動ボタンを押した時の処理スクリプトClickButton

シーンを移動するボタンを押した時の処理スクリプトClickButtonを作成します。

ClickButtonはボタンを押した時に呼び出すスクリプトで、UIの大元であるCanvasに設定します。

スクリプトが長いので少しづつ解説します。

フィールドの宣言部

fadeSpeedはフェードイン、フェードアウトのスピードを設定します。

fadeImageはフェードに使うヒエラルキーのImageオブジェクトを設定します。

unLoadSceneは新しいシーンを読み込んだ時に、現在のシーンを入れておく為のもので、後でアンロードします。

buttonPanelはヒエラルキーのButtonオブジェクトを設定します。

Startメソッド

Startメソッドではまずボタンパネルを非アクティブにします。

これはフェード中にボタンが押せるようにすると不具合が発生するので、フェード中はシーン遷移ボタンを表示しないようにします。

その後コルーチンを使ってFadeメソッドを呼び出し、Imageのアルファ値を0にしてImageが完全に透明になるようにします。

スクリプトの名前がClickButtonですが、シーン遷移の処理も詰め込んでいます。

ButtonEventメソッド

ButtonEventメソッドは、シーン移動ボタンを押した時に実行させる予定のメソッドです。

引数として読み込むシーン名を受け取ります。

ボタンが押されたらすぐにボタンを非表示にし、Imageの不透明度を上げて、カメラに映る他のUIやゲームオブジェクトを見えないようにします。

次にFadeAndLoadSceneをコルーチンで実行します。

FadeAndLoadScene

FadeAndLoadSceneではフェードアウトをまず実行し、現在のシーンをunLoadSceneに保存しておきます。

フェードアウトが完了したら次のシーンをロードし、現在のシーンをアンロードします。

Fadeメソッド

Fadeメソッドは引数として最終的に変更するアルファ値を受け取ります。

whileの条件ではImageのアルファ値と最終的なアルファ値とを比較し、違う場合は繰り返し実行します。

yield return nullに関してはコルーチンの記事を参照してください。

Unityでコルーチンを使うと定期的に何らかの処理を行える事が出来るようになります。一見解り辛いけど使い方がわかれば便利かも!?

フェードが終わったら、シーン遷移ボタンを表示します。

LoadNewSceneメソッド

LoadNewSceneは引数で受け取ったシーンを読み込みます。

読み込みが終わったらシーンをアクティブにします。

UnLoadSceneメソッド

UnLoadSceneでは現在のシーンをアンロードし、ヒエラルキー上から消します。

UnLoadSceneAsyncは非同期でシーンを読み込む処理ですが、わたくしが主に使っているUnity5.3.4f1では定義されていません。(^_^;)

そんな時はUnLoadSceneを使いますが、5.6バージョンでは非奨励の処理になっていますね。

データ表示更新のShowDataスクリプト

DataTextゲームオブジェクトにShowDataスクリプトを新しく作り、設定します。

publicでMyData型のdataを宣言し、インスペクタでData.assetを設定します。

Startメソッドでdataのフィールドを表示しています。

UpdateTextメソッドも同じ事をしていますが、こちらはデータの更新があった時の他のスクリプトから実行されます。

あ・・・、同じ処理ならStartメソッド内でUpdateTextメソッド呼べばいいね・・・・(-.-)

データの書き換えをするChangeDataスクリプト

ChangeDataゲームオブジェクト(ボタン)にChangeDataスクリプトを新しく作り、取り付けます。

publicでMyData型のdataフィールドを宣言し、インスペクタでData.assetを設定します。

Changeメソッドが呼ばれると、dataのフィールド値をランダムに書き換え、先ほど作成したShowDataスクリプトをFindObjectOfTypeで探し、UpdateTextメソッドを実行し、テキストの中身を更新します。

ShowDataをFindObjectOfTypeで検索していますが、publicでShowDataスクリプトを設定しておいた方が処理が早いかもしれません。

次にChangeDataボタンのインスペクタのOn Clickで、自身に取り付けたChageDataスクリプトのChangeメソッドを設定します。

ChangeDataスクリプトのChangeメソッドを実行させる

ChangeDataボタンのインスペクタは↑のようになります。

ボタンを押した時に実行するメソッドを指定するやり方は、

Unityでタイトル画面に表示するスタートボタン、ゲーム終了ボタンのUIを作成していきます。シーン移動や画面遷移をしたい時にボタンを押す事で移動出来るようにします

を参照してください。

シーン移動ボタンを押した時に実行するメソッドの設定

SecondSceneButtonとThirdSceneButtonのインスペクタのOn ClickにCanvasをドラッグ&ドロップし、実行するメソッドにButtonEventを設定します。

シーン移動ボタンを押した時に実行するメソッドの指定

設定されると引数に渡す文字列の入力欄が表れるので、そこに遷移するシーン名を記述します。

シーン移動ボタンを押した時にButtonEventを実行する

↑はSecondSceneButtonの設定で、Secondを入力し、ButtonEventの引数に渡ります。

Secondシーン、Thirdシーンではボタンを押した時に渡す文字列などを変更します。

これで機能が完成しました。

シーンをビルドセッティングに登録する

ゲームに使うシーンはあらかじめビルドセッティングに登録しておく必要があります。

Unityのメニュー項目→Build Settings…を選択します。

シーンをビルドセッティングに登録

Scenes In Buildに作成した4つのシーンをドラッグ&ドロップします。

Mainシーンをドラッグし、一番上に移動させて一番最初に再生するようにします。

またData.assetのmyNameに何か名前を指定しておいてください。

これでビルドセッティングも出来たので、ビルドして機能を確認してみます。

シーン間でのデータの共有を確認

それでは実行してみます。

↑のようになりました。

シーンを移動してのデータ共有が簡単になりました!

もちろんゲームを終了した時はData.assetのデータも消えるので、別途何かにデータを保存する必要はありますね。

ScriptableObjectを使った例として次回以降でRPGのワールドマップ→戦闘シーン→ワールドマップという一連の流れを作ってみたいと思います。

スポンサーリンク

記事をシェアして頂ける方はこちら

フォローして頂くとやる気が出ます