シーン間のデータ受け渡し
Unityでは、シーンをLoadSceneで切り替えるとデータが破棄され引き継げません
引き継ぐ方法は様々ありますが、Unityでの推奨をご紹介したいと思います
スクリプタブルオブジェクトを使ったデータの受け渡し
スクリタプルオブジェクトは、シーン間のデータの受け渡しのみならず、パラメータの保存等に活用することができます
データの保存が目的の場合・・・
ハイスコアなど、結果シーンでもデータを利用したい場合、スクリプタブルオブジェクトを検討してみましょう
準備
スクリプタブルオブジェクト作成用のコード
このコードを作成後、下のスクリプタブルオブジェクトを作成を実行します
このコードでは、保存したいデータの他にCreateメニューにスクリプタブルオブジェクトの作成も行うコードが属性として追加されています
using UnityEngine;
[CreateAssetMenu(menuName = "Data")]
public class DataKeep : ScriptableObject
{
public int score;
}
スクリプタブルオブジェクトを作成
プロジェクトウィンドウで、右クリック → Create → Dataを選択
ファイル名入力になりますので、Dataとします
作成されたファイルをクリックすると、インスペクタに情報が表示されます
シーン構成
シーン切り替え時にデータがうまく渡せたか確認するため、2つのシーンを作成します
シーン1
最初のシーンです。
スペースキーを押すと、scoreに100を代入後、シーンを2に切り替えるスクリプトがアタッチされています
インスペクターのDataには、プロジェクトウィンドウからDataファイルをアウトレット接続します
using UnityEngine;
using UnityEngine.SceneManagement;
public class DataWrite : MonoBehaviour
{
[SerializeField]
DataKeep data;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
data.score = 100;
SceneManager.LoadScene("Scene2");
}
}
}
シーン2
シーンが切り替わり、Startメソッドが呼び出させるとコンソールにscoreの値が表示されます
インスペクターのDataには、プロジェクトウィンドウからDataファイルをアウトレット接続します
using UnityEngine;
public class DataRead : MonoBehaviour
{
[SerializeField]
DataKeep data;
void Start()
{
Debug.Log(data.score);
}
}
実行結果
コードで変更(コードで代入)しても保存されません(一見保存されているように見えても再起動で戻っています)
コードで変更しても保存したい場合
この方法は、Unityエディター限定です。PCやスマホでビルドして機能させることはできません。
ビルドした時は、最後に書き出したデータが使われます
ハイスコアなどのデータ保持の場合はこれを使いましょう
ただしインスペクターで値を変更する場合は、すぐ保存されます
次のコードを追加します
EditorUtility.SetDirty(data);
AssetDatabase.SaveAssets();
今回のサンプルでは次のようになります
using UnityEditor;
using UnityEngine;
using UnityEngine.SceneManagement;
public class DataWrite : MonoBehaviour
{
[SerializeField]
DataKeep data;
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
data.score = 100;
EditorUtility.SetDirty(data);
AssetDatabase.SaveAssets();
SceneManager.LoadScene("Scene2");
}
}
}
スクリプタブルオブジェクトは、最後に更新された値がエディター上では残っています。呼び出し元のコードで初期化してもいいですが、スクリプタブルオブジェクト自身で初期化してほしい場合、次のようにすれば可能です
スクリプタブルオブジェクトを起動都度初期化
今回のサンプルでは次のようになります
using UnityEngine;
[CreateAssetMenu(menuName = "Data")]
public class DataKeep : ScriptableObject
{
[SerializeField]
int initScore;
public int Score;
// インスペクターに表示したくなければ・・・こちら
//public int Score { get; set; }
private void OnEnable()
{
Score = initScore;
}
}
参考
スクリプタブルオブジェクトの内容
テキストファイルになっています。最終行がscoreになってますね
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 88881a02bc6a14eb08bbc76d3d3ae587, type: 3}
m_Name: Data
m_EditorClassIdentifier:
score: 100
ディスカッション
コメント一覧
まだ、コメントがありません