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/)
それでは、今回のお話はこれまでになります。