柴犬 API に Unity でつなげてみるメモ

柴犬 API に Unity でつなげてみるメモです。

この記事は 2022年 ゆるくすすめる ( ワンフットシーバス ) | GWアドベントカレンダー の 5/7 9日目の記事でもあります。

柴犬 API を Unity でつなげたら色々学びがあった

かわいい柴犬画像が取得できる shibe.online に Unity からつなぎこんでみまして、JsonUtility.FromJson による JSON 化したりや、最近 isNetworkError、isHttpError が非推奨になって書き換えて個人的に学びがあったのでメモしておきます。

実際に動くコードはこちら

今回は API からの読み込みだけやりたいので、画像ロード後にテクスチャで何かに貼るような対応は抜いています。

2020.3.30f の Unity でプログラムを書きました。

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public class ShibainuSimple : MonoBehaviour
{
    
    // JSON データ化するクラス
    [Serializable]
    public class ShibaData
    {
        public List<string> urls;
    }

    void Start()
    {
        StartCoroutine(GetShibainu());
    }

    IEnumerator GetShibainu()
    {
        // 3 つの柴犬画像を取得するURL
        UnityWebRequest request = UnityWebRequest.Get("http://shibe.online/api/shibes?count=3&urls=true&httpsUrls=true");

        yield return request.SendWebRequest();

        // まずテキストデータとして取得
        string json = (string)request.downloadHandler.text;

        Debug.LogFormat("json: {0}", json);

        // ルートが配列なので JSON 化する前に urls オブジェクトで包んで調整する
        json = "{\"urls\":" + json + "}";

        // そのうえで ShibaData クラスで JSON データ化
        ShibaData shibaData = JsonUtility.FromJson<ShibaData>(json);

        switch (request.result)
        {
            case UnityWebRequest.Result.InProgress:
                Debug.Log("リクエスト中");
                break;

            case UnityWebRequest.Result.Success:
                Debug.Log("リクエスト成功");

                // 3 つの柴犬画像 URL をリストアップ
                Debug.LogFormat("1: {0}", shibaData.urls[0]);
                Debug.LogFormat("2: {0}", shibaData.urls[1]);
                Debug.LogFormat("3: {0}", shibaData.urls[2]);

                break;
        }


    }

}

こちらを実行すると、

image

このように 3 つの柴犬画像 URL をリストアップされます。

ルートが配列だとうまくいかないので調整

柴犬 API がルートが配列なので ArgumentException: JSON must represent an object type. というエラーが出てしまい困りました。FromJson の制約の一つとのことです。

【Unity】JsonUtilityで配列とリストを処理する – PG日誌

こちらの記事が参考になりました。

これは、API から吐き出すデータをJSON 化する前に urls オブジェクトで包んで調整するようにしました。

        // まずテキストデータとして取得
        string json = (string)request.downloadHandler.text;

        Debug.LogFormat("json: {0}", json);

        // ルートが配列なので JSON 化する前に urls オブジェクトで包んで調整する
        json = "{\"urls\":" + json + "}";

        // そのうえで ShibaData クラスで JSON データ化
        ShibaData shibaData = JsonUtility.FromJson<ShibaData>(json);

配列で帰ってくる API は他でもあり得そうなので、この手法は応用しやすそうです。

isNetworkError、isHttpError が非推奨なので書き換え

image

以前から、良く書いてたコードで非推奨のメッセージが出ました。

【Unity】Unity 2020.2 新機能 – UnityWebRequest の isNetworkError、isHttpError が非推奨になった – コガネブログ

こちらの記事が参考になりまして、書き換えることにしました。

        switch (request.result)
        {
            case UnityWebRequest.Result.InProgress:
                Debug.Log("リクエスト中");
                break;

            case UnityWebRequest.Result.Success:
                Debug.Log("リクエスト成功");

                // 3 つの柴犬画像 URL をリストアップ
                Debug.LogFormat("1: {0}", shibaData.urls[0]);
                Debug.LogFormat("2: {0}", shibaData.urls[1]);
                Debug.LogFormat("3: {0}", shibaData.urls[2]);

                break;
        }

今回は、リクエスト中とリクエスト成功のときだけ判定するようにして、リクエスト成功後に 3 つの柴犬画像 URL をリストアップをしています。

この書き方だと、より色々な状態を case で捉えられるのでいいですね!

ついつい JSON 変換を MiniJSON を使いがちだったのを JsonUtility で事前にデータ構造をクラスで決めてからちゃんと読み込むように書けたことと、ルートが配列で来るときの対処法が抑えられてスッキリしました。また、リクエスト後の UnityWebRequest.Result の書き方が体験できたので、今後に活用できそうです。