4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ScriptableObject を JSONから読み込む

Posted at

Unityでデータを量産する場合、ScriptableObject は大変便利です。

[CreateAssetMenu(fileName = "SampleDataSO", menuName = "ScriptableObject/SampleDataListSO")]
public class SampleDataSO : ScriptableObject
{
    public SampleData[] samples;
}

上記のようなScriptableObjectであれば
Create> ScriptableObject> SampleDataListSO
image.png
でオブジェクトを作成することができ、直接データを作っていくことができます。
image.png

作成したデータをそのまま利用する場合は問題ないのですが、JSON経由でやりとりしたい場合、ScriptableObjectはCreateInstance<>()でインスタンスを生成する必要があるため、通常のデータクラスのように
SampleDataSO data = JsonUtility.FromJson<SampleDataSO>(jsonString);
とすると

Failed to load settings data: Cannot deserialize JSON to new instances of type 'SampleDataSO.'

といったエラーが出てしまいます。
そこでScriptableObjectでは
JsonUtility.FromJsonOverwrite(json, data);
を使用します。

SampleDataSO.cs
using JetBrains.Annotations;
using UnityEngine;

[System.Serializable]
public class PersonData
{
    public string name;
    public int age;
}
[System.Serializable]
public class HobbyData
{
    public string hobby;
    public float hours;
}
[System.Serializable]
public class SampleData
{
    public PersonData person;
    public HobbyData[] hobbies;
}

[CreateAssetMenu(fileName = "SampleDataSO", menuName = "ScriptableObject/SampleDataListSO", order = 1)]
public class SampleDataSO : ScriptableObject
{
    public SampleData[] samples;

    // ScriptableObjectをCreateInstance()するにはJsonUtility.FromJsonOverwriteが必要
    public static SampleDataSO CreateScriptableObjectFromJSON(string jsonString)
    {
        SampleDataSO data = CreateInstance<SampleDataSO>();
        JsonUtility.FromJsonOverwrite(jsonString, data);
        return data;
    }
}

以下のサンプルは、上記ScriptableObjectをJSON形式でファイルに保存し、再びScriptableObjectに戻します。

ScriptableObjectJSONSample.cs
using System;
using UnityEngine;

public class ScriptableObjectJSONSample : MonoBehaviour
{
    [SerializeField] string m_dataPath = "SampleData.json";
    [SerializeField] SampleDataSO m_sampleDataSO;

    // Start is called before the first frame update
    void Start()
    {
        SaveToJSON(m_dataPath, m_sampleDataSO);
        SampleDataSO importedDataSO = LoadfromJSONFile(m_dataPath);
        string jsonStr = JsonUtility.ToJson(importedDataSO, true);
        Debug.Log("ImportedData: \n" + jsonStr);
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    public static string GetFullPath(string _dataPath)
    {
#if !UNITY_EDITOR
        string appPath = Application.persistentDataPath;
#else
        string appPath = Application.dataPath;
#endif
        return $"{appPath}/{_dataPath}";
    }

    public static bool SaveToJSON(string _dataPath, SampleDataSO _dataSO)
    {
        bool result = false;
        string fullPath = GetFullPath(_dataPath);
        // ファイルにデータを書き込む
        string jsonStr = JsonUtility.ToJson(_dataSO, true);
        Debug.Log("SaveSettings: " + fullPath);
        try
        {
            System.IO.File.WriteAllText(fullPath, jsonStr);
            result = true;
        }
        catch (Exception e)
        {
            Debug.LogError("Failed to save settings data: " + e.Message);
        }
        return result;
    }

    public static SampleDataSO LoadfromJSONFile(string _dataPath)
    {
        string fullPath = GetFullPath(_dataPath);

        // ファイルからデータを読み込む
        string jsonStr = System.IO.File.ReadAllText(fullPath);

        try
        {
            SampleDataSO data = SampleDataSO.CreateScriptableObjectFromJSON(jsonStr);
            return data;
        }
        catch (Exception e)
        {
            Debug.LogError("Failed to load settings data: " + e.Message);
            return null;
        }
    }
}

結果:

ImportedData: 
{
    "samples": [
        {
            "person": {
                "name": "アンドリュー",
                "age": 64
            },
            "hobbies": [
                {
                    "hobby": "彫刻",
                    "hours": 6.0
                },
                {
                    "hobby": "自分探しの旅",
                    "hours": 1.0
                }
            ]
        },
        {
            "person": {
                "name": "ポーシャ",
                "age": 32
            },
            "hobbies": [
                {
                    "hobby": "ピアノ演奏",
                    "hours": 2.0
                }
            ]
        }
    ]
}

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?