【大阪 / 横浜】インフラ / サーバーサイドエンジニア募集中!

【大阪 / 横浜】インフラ / サーバーサイドエンジニア募集中!

【導入実績 500社以上】AWS 構築・運用保守・監視サービス

【導入実績 500社以上】AWS 構築・運用保守・監視サービス

【CentOS 後継】AlmaLinux OS サーバー構築・移行サービス

【CentOS 後継】AlmaLinux OS サーバー構築・移行サービス

【WordPress 専用】クラウドサーバー『ウェブスピード』

【WordPress 専用】クラウドサーバー『ウェブスピード』

【格安】Webサイト セキュリティ自動診断「クイックスキャナー」

【格安】Webサイト セキュリティ自動診断「クイックスキャナー」

【低コスト】Wasabi オブジェクトストレージ 構築・運用サービス

【低コスト】Wasabi オブジェクトストレージ 構築・運用サービス

【予約システム開発】EDISONE カスタマイズ開発サービス

【予約システム開発】EDISONE カスタマイズ開発サービス

【100URLの登録が0円】Webサイト監視サービス『Appmill』

【100URLの登録が0円】Webサイト監視サービス『Appmill』

【中国現地企業に対応】中国クラウド / サーバー構築・運用保守

【中国現地企業に対応】中国クラウド / サーバー構築・運用保守

【YouTube】ビヨンド公式チャンネル「びよまるチャンネル」

【YouTube】ビヨンド公式チャンネル「びよまるチャンネル」

UnityWebRequest で簡単 HTTP(POST)通信

お疲れ様です。
システム開発室、松山です。

今回は UnitWebRequest を使った HTTP(POST) 通信について書いていきます。
今更感満載ですが、私が www での通信しか実装してなかったので改めて ^^;

作るもの

・UnitWebRequst で HTTP(POST)通信
・リクエスト、レスポンスは JSON 形式
・複数の通信 API を作成する想定でシンプルに
※ Unity 2019.3.5f1 で作成

JSON

まず JSON ですが、Unity の JsonUtility を使って実装します。
JsonUtility は Unity が提供している Json パーサで、
Serializable 指定されたクラスや構造体を用意にシリアライズできます。
Dictionary 型はサポート外など制約もありますが、パフォーマンス面で他の Json パーサより優れているようです。
Json 形式にシリアライズ

UnityWebRequest

今回メインの通信処理です。
UnityWebRequest で HTTPリクエストとレスポンスを扱うことができます。
UnityWebRequest

処理自体はかなりシンプルに書けました。
UnityWebRequest を POST形式で生成し、リクエストパラメータをjson形式で設定します。

    // HTTP(POST)の情報を設定
    var req = new UnityWebRequest(url, "POST");
    req.uploadHandler = (UploadHandler)new UploadHandlerRaw(postData);
    req.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
    req.SetRequestHeader("Content-Type", "application/json");

1点注意なのは、パラメータは string のままでは渡せないため、byte配列に変換することでしょうか。

    // リクエストオブジェクトを JSON に変換(byte配列)
    string reqJson = JsonUtility.ToJson(request);
    byte[] postData = System.Text.Encoding.UTF8.GetBytes(reqJson);

準備できたらリクエストを投げます。

    // API 通信(完了待ち)
    yield return req.SendWebRequest();

通信結果は isNetworkError と isHttpError がともに false であることで成功と判定しました。
レスポンスはdownloadHandler に Json形式(text)で格納されます。

    // 通信結果
    if (req.isNetworkError ||
        req.isHttpError)  // 失敗
    {
        Debug.Log("Network error:" + req.error);
    }
    else                  // 成功
    {
        Debug.Log("Succeeded:" + req.downloadHandler.text);
    }

API 制御

上述の通信処理を基底クラスとして、各API のリクエストとレスポンスを定義した APIクラスを作成するイメージ。
具体的にはこういった形でしょうか。
リクエストとレスポンス用の構造体を Serializable 属性で作成し、パラメータを定義。
通信時の URL は共通部分を基底クラス側で定義するので、末尾の API 名を定義。

using System;
using System.Collections.Generic;

namespace Api
{
    /// <summary>
    /// API サンプルB
    /// </summary>
    public class SampleB : Web.ApiBase
    {
        public const string Name = "Test/SampleB";

        /// <summary>
        /// リクエストパラメータ
        /// </summary>
        [Serializable]
        public struct Request
        {
            public string userId;
            public List<int> values;
        }
        public Request request;

        /// <summary>
        /// レスポンスパラメータ
        /// </summary>
        [Serializable]
        public struct Response
        {
            public int count;
            public List<int> values;
        }
        public Response response;
    }
}

使い方

まず、上述の API クラスを生成。

    private Api.SampleB         apiB;
    private Web.ApiBase.Result  result;

    private void Start()
    {
        // 通信用クラス生成
        apiB = new Api.SampleB();

        // API 通信
        sendApiB();
    }

API 名を指定したら、リクエスト構造体に渡す値を設定。
メソッド Send() 内で JSON 形式にシリアライズされ、UnityWebRequest で HTTP(POST) 通信されます。
通信完了をコールバックで受け取り、レスポンス構造体へデシリアライズします。
本来はレスポンスの内容に応じて処理を書くと思いますが、サンプルなのでコンソールに出力するだけにしています。

    /// <summary>
    /// API サンプルB 通信
    /// </summary>
    private void sendApiB()
    {
        // エンドポイントの設定
        apiB.EndPoint = Api.SampleB.Name;
        // リクエストパラメータを設定
        apiB.request.userId = "beyondB";
        apiB.request.values = new List<int>() { 1, 10, 100, 1000 };

        // 通信
        apiB.Send<Api.SampleB.Request>(ref apiB.request, result => {
            // リザルト
            if (result.isSucceeded)  // 成功
            {
                // レスポンスを展開
                apiB.response = apiB.Response<Api.SampleB.Response>();

                // 内容確認
                Debug.Log("SampleB Succeed!!");
                Debug.Log("  count : " + apiB.response.count);
                foreach(var v in apiB.response.values)
                {
                    Debug.Log("  val : " + v);
                }
            }
            else                    // 失敗
            {
                Debug.Log("SampleB Failed : " + result.error);
            }
        });
    }

まとめ

といった形で、かなりシンプルに HTTP通信処理を書くことができました。
とりあえず実用にも耐えるのではないかなと思います。
通信処理なのでサーバー側の実装がないと動作しませんが、一応サンプルコードを GitHub に上げておきます。
Unity サンプル

サンプルの基底クラスでは MonoBehaviour を継承していないので、そのままではコルーチンが使えませんでした。
こちらを参考に対応しています。
MonoBehaviorを継承しないクラスでコルーチンを使う

最後に

私が所属するシステム開発のサービスサイト「SEKARAKU Lab(セカラク ラボ)」を開設しました。
ビヨンドは、サーバーの設計・構築から運用までをワンストップでお任せいただけますので、サーバーサイド開発でお困りの方はお気軽にお問い合わせください。
SEKARAKU Lab:[https://sekarakulab.beyondjapan.com/](https://sekarakulab.beyondjapan.com/)

それでは、今回のお話はこれまでになります。

この記事がお役に立てば【 いいね 】のご協力をお願いいたします!
2
読み込み中...
2 票, 平均: 1.00 / 12
12,101
X facebook はてなブックマーク pocket
【2024.6.30 CentOS サポート終了】CentOS サーバー移行ソリューション

【2024.6.30 CentOS サポート終了】CentOS サーバー移行ソリューション

【大阪 / 横浜】インフラエンジニア・サーバーサイドエンジニア 積極採用中!

【大阪 / 横浜】インフラエンジニア・サーバーサイドエンジニア 積極採用中!

この記事をかいた人

About the author

松山賢勝

長くゲーム開発会社でプログラムやプロジェクトマネージメントなどの業務に従事。
2019年より株式会社ビヨンド に入社。横浜オフィスに勤務。
サーバーサイド開発業務のプロジェクトマネージメントを中心に担当。(時々、プログラミング)
趣味は自転車(ロードレーサー)と競馬観戦。