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