Unity - EditorJsonUtility:Prehab などの UnityEngine.Object のデータを保存する -
初めに
データのセーブ・ロードに JsonUtility が用いられますが、似たような機能に EditorJsonUtility が存在します。EditorJsonUtility についてまとめます。
Index
JsonUtility との違い
UnityEngine.Object のシリアライズ、デシリアライズについて
結論から述べると
アセットを参照する場合は、JsonUtility ではなく、EditorJsonUtility を用いる
Prehab のデータを参照し、JSON に保存します。
次のスクリプトをゲームオブジェクトにつけ、実行してみます。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor; //AssetDatabaseを使うために追加 using System.IO; //StreamWriterなどを使うために追加 using System.Linq; //Selectを使うために追加 public class EditorJsonScript : MonoBehaviour { //保存先 string[] datapath; //初期値で保存するオブジェクト public GameObject _obj; void Awake() { //保存先の計算をする //これはAssets直下を指定. /以降にファイル名 datapath = new string[2]; datapath[0] = Application.dataPath + "/TestJsonUtility.json"; datapath[1] = Application.dataPath + "/TestEditorJsonUtility.json"; } // Start is called before the first frame update void Start() { //playerデータを取得 Obj obj = new Obj (); //JSONファイルがあればロード, なければ初期化関数へ if(FindJsonfile()) { obj = loadPlayerData(); } else { Initialize(obj); } } //セーブするための関数 public void savePlayerData(Obj obj) { StreamWriter writer; //playerデータをJSONに変換 string jsonstr = JsonUtility.ToJson (obj); string edijsonstr = EditorJsonUtility.ToJson (obj); Debug.Log("jsonstr:" + jsonstr); Debug.Log("edijsonstr:" + edijsonstr); //JSONファイルに書き込み for(int i = 0; i < datapath.Length; i++) { writer = new StreamWriter(datapath[i], false); writer.Write (jsonstr); writer.Flush (); writer.Close (); } } //JSONファイルを読み込み, ロードするための関数 public Obj loadPlayerData() { string datastr = ""; StreamReader reader; reader = new StreamReader (datapath[0]); datastr = reader.ReadToEnd (); reader.Close (); return JsonUtility.FromJson<Obj> (datastr); } //JSONファイルがない場合に呼び出す初期化関数 //初期値をセーブし, JSONファイルを生成する public void Initialize(Obj obj) { obj.obj = _obj; savePlayerData(obj); } //JSONファイルの有無を判定するための関数 public bool FindJsonfile() { string[] assets = AssetDatabase.FindAssets(datapath[0]); Debug.Log(assets.Length); if(assets.Length != 0) { string[] paths = assets.Select(guid => AssetDatabase.GUIDToAssetPath(guid)).ToArray(); Debug.Log($"検索結果:\n{string.Join("\n", paths)}"); return true; } else { Debug.Log("Jsonファイルがなかった"); return false; } } } //Playerのデータとなるクラスの定義 [System.Serializable] public class Obj { public GameObject obj; }
(実行結果)
この結果からわかることは次の通りです。
インスタンスIDはインスタンス生成時に生成されるため、再起動した場合、インスタンスIDは変わってしまいます。そのため、アセットから正しく参照できません。
Prehab を使うなどアセットを参照する場合は、EditorJsonUtility を用いたほうがよいでしょう。
最後に
JsonUtility はバックグランドスレッドで使えるが、EditorJsonUtility はバックグランドスレッドで使えないという違いもあるようです。