【Unity JsonUtility】(クラスの配列)オブジェクトのデータを保存する方法

2021年3月18日

UnityのJsonUtilityで扱える情報として、クラスから作られたインスタンスがあります。

基本となるクラス

参考

参考リンクように、シリアライズ化されたクラスでの保存・読み出しは問題なく行えます。

では、このクラスの配列をそのままの状態で保存することを試みましょう。
次のクラスを前提に考えてみます。

// 商品のインスタンスをインスペクターに表示させます。productは、Product型のフィールドになります。
[SerializeField]
Product product;

// 商品クラスをシリアライズ
[Serializable]
class Product
{
    // 商品名
    public string Name;

    // 賞味期限
    public string Expiry;

    // 大きさの種類
    public string[] Sizes;
}

作成したクラスを配列として扱う

参考

では、この基本クラスを配列にしたものはどうでしょうか?

次のコードを実行すると、productJsonには、{}が代入されます。

うまくできていないようです。

失敗するコード

using System;
using UnityEngine;

// 商品クラスをシリアライズ
[Serializable]
class Product
{
    // 商品名
    public string Name;

    // 賞味期限
    public string Expiry;

    // 大きさの種類
    public string[] Sizes;
}

public class ArrayTest : MonoBehaviour
{
    [SerializeField]
    Product[] products;

    void Start()
    {
        var productJson = JsonUtility.ToJson(products, true);
    }
}

成功するコード

直接、配列をJsonフォーマットへの試みるのではなく、一旦、その配列をメンバーとするクラスを作成して、そのインスタンスをJsonフォーマットにします。
これを、ラッパー(ラップですね。食品を包み込むイメージです)と言います。

using System;
using UnityEngine;

/// <summary>
/// ラッパー(包む、食品を包むラップのようなもの)
/// 配列は、UnityのJsonUtirityで直接管理できないため、配列をクラスのメンバーとして使います。
/// </summary>
[Serializable]
class ProductWrapper
{
    // 商品のインスタンス(配列)をインスペクターに表示させます。productは、Product型のフィールドになります。
    public Product[] products;
}

// 商品クラスをシリアライズ
[Serializable]
class Product
{
    // 商品名
    public string Name;

    // 賞味期限
    public string Expiry;

    // 大きさの種類
    public string[] Sizes;
}


public class ArrayTest : MonoBehaviour
{
    [SerializeField]
    ProductWrapper productsWrap;

    void Start()
    {
        // データの更新は次のようにできます。
        productsWrap.products[1].Name = "キャベツ";

        var productsArray = JsonUtility.ToJson(productsWrap, true);

        Debug.Log(productsArray);

        // 保存処理をコーディング(略)

    }
}

(参考)foreachで確認する場合

using System;
using UnityEngine;

public class SirializeClass : MonoBehaviour
{
    [SerializeField]
    // 商品のインスタンス(配列)をインスペクターに表示させます。productは、Product型のフィールドになります。
    Product[] products;

    [Serializable]
    // 商品クラスをシリアライズ
    class Product
    {
        // 商品名
        public string Name;

        // 賞味期限
        public string Expiry;

        // 大きさの種類
        public string[] Sizes;
    }

    void Start()
    {
        // 全てのインスタンスを表示
        foreach (Product product in products)
        {
            Debug.Log($"{product.Name} {product.Expiry}");

            // インスタンスごとのサイズを全て表示
            foreach (string size in product.Sizes)
            {
                Debug.Log($”{size}");
            }
        }
    }
}

2021年3月18日Unity

Posted by hidepon