Apeiria Tech

セキュリティ・ゲーム開発(Unity)

Addressable Asset SystemからJsonをロードしてテキストを表示したい

はじめに

タイトルの通り Addressable Asset System(AAS)からJsonをロードしてテキストを表示するときに
詰まった点と解決方法の共有記事です。

環境

Unity 2021.3.8f1
Addressables 1.19.19

詰まった点

以下のJsonファイル(test.json)をAASを使ってロードします。

{
    "loadItem": [
        {
            "x": "Jsonからテキスト読み取り"
        }
    ]
}

以下のコードを適当なGameObjectにアタッチして再生します。

using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
using UnityEngine.AddressableAssets;

[System.Serializable]
public class LoadData
{
    public MainItemData[] loadItem;
}
[System.Serializable]
public class MainItemData
{
    public string x;
}
public class InputToJson : MonoBehaviour
{
    [SerializeField]
    Text dialogue = default;
    void Start()
    {
        LoadData loadData = new LoadData();

        loadData.loadItem = new MainItemData[3];

        string inputString = Addressables.LoadAssetAsync<TextAsset>("test").ToString();
        Debug.Log("inputString..." + inputString);

        LoadData inputJson = JsonUtility.FromJson<LoadData>(inputString);

        dialogue.DOText(inputJson.loadItem[0].x, 2).SetEase(Ease.Linear);
    }
}

すると

ArgumentException: JSON parse error: Invalid value.

となり、parse errorと表示されます。 また、inputStringをDebu.Logで確認してみると AsyncOperationHandleが読み込まれています。

解決方法

Addressables.LoadAssetAsync は非同期で、ロードが完了するまで待つ必要があります。 ロードが完了していない状態でToStringsしていたのでAsyncOperationHandleがinputStringに入っていたようです。
Addressbles1.17.4から同期ロードの公式サポートが始まったので
WaitForCompletion()を使って同期的に待機します。 async/awaitでもできると思いますが今回は手っ取り早いこちらの方法でやります。 以下修正したコード

using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
using UnityEngine.AddressableAssets;

[System.Serializable]
public class LoadData
{
    public MainItemData[] loadItem;
}
[System.Serializable]
public class MainItemData
{
    public string x;
}
public class InputToJson : MonoBehaviour
{
    [SerializeField]
    Text dialogue = default;
    void Start()
    {
        LoadData loadData = new LoadData();

        loadData.loadItem = new MainItemData[3];

        //string inputString = Addressables.LoadAssetAsync<TextAsset>("test").ToString();
       //↓同期的に待機
        string inputString = Addressables.LoadAssetAsync<TextAsset>("test").WaitForCompletion().ToString();

        Debug.Log("inputString..." + inputString);

        LoadData inputJson = JsonUtility.FromJson<LoadData>(inputString);

        dialogue.DOText(inputJson.loadItem[0].x, 2).SetEase(Ease.Linear);
    }
}

無事動きました。文字送りはDOTweenを使っています。

おわりに

同期・非同期の理解がまだ浅いなと感じました...。