Unity

UnityでHTTPリクエストを処理してみる

Unityのゲームを動かしている間に外からHTTPでメッセージを送って制御したりするのをやりたかったので、ゲーム内でHTTPリクエストを処理する方法を調べました。

.NETに標準で搭載されているHttpListenerを使うことでHTTPリクエストを受け付ける処理を書くことができます。最近のUnityではスクリプトランタイムを.NET 4.6環境に設定することができてasync/awaitを使うこともできるので、より簡潔な方法で記述することができるようになりました。

本記事ではさらにUnityのイベントシステムと組み合わせることで、クリックイベントなどと同じような感覚でHTTPリクエストを処理できるようなしくみを作ってみました。

HTTPサーバーのコンポーネントを作る

まず、以下のようなスクリプトを書きます。

HttpServer.cs
using System.Net;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[System.Serializable]
public class OnRequestEvent : UnityEvent<HttpListenerContext> { }

public class HttpServer : MonoBehaviour
{
  private HttpListener httpListener = new HttpListener();

  // エディター上から設定する
  public int port = 8080;
  public string path = "/";
  public bool startOnAwake = true;

  // リクエスト処理するイベントハンドラー。エディター上から設定する。
  public OnRequestEvent OnRequest;

  void Start()
  {
    httpListener.Prefixes.Add("http://*:" + port + path); // http://*:8080/ のようになる

    // コンポーネントの開始時に自動起動
    if (startOnAwake)
    {
      StartServer();
    }
  }

  // リクエストの受け付けを開始する
  public async Task StartServer()
  {
    httpListener.Start();

    while (true)
    {
      // リモートからの接続を待機
      var context = await httpListener.GetContextAsync();

      // 着信ログを表示
      Debug.Log("Request path: " + context.Request.RawUrl);

      OnRequest.Invoke(context);
    }
  }

  // サーバーを停止する
  public void StopServer()
  {
    httpListener.Stop();
  }

  // 破棄時にサーバーを止める
  void OnDestroy()
  {
    StopServer();
  }
}

そして、シーンに空のゲームオブジェクトを作成して、上記スクリプトをアタッチします。

キャプチャ.PNG

こんな感じになると思います。

HTTPリクエストを処理する

もう一つ空のゲームオブジェクトを作り、以下のようなスクリプトを書きます。

MyRequestHandler.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net;

public class MyRequestHandler : MonoBehaviour
{
  public string message = "Hello from Unity!";

  public void OnRequest(HttpListenerContext context)
  {
    // message の内容をバイト配列に変換してレスポンスを返す
    var data = System.Text.Encoding.UTF8.GetBytes(message);
    context.Response.StatusCode = 200;
    context.Response.Close(data, false);
  }
}

スクリプト同士をくっつける

最後に、HTTPサーバーのスクリプトとHTTPリクエストを処理するスクリプトをくっつけます。HTTPサーバーのゲームオブジェクトを選択してインスペクターのOn Request (HttpListenerContext)の部分の右下の+アイコンを選択して項目を一つ増やします。
2.PNG

None (Object)の右の丸いポチを選択して、先程HTTPリクエストを処理するスクリプトを設定したゲームオブジェクトを選択します。
3.PNG

No FunctionのドロップダウンからMyRequestHandler→OnRequestの順に辿ります。
4.PNG

こんな感じになったらOKです。
5.PNG

動かしてみる

さてここまでできたら、ゲームを動かしてみましょう。ブラウザを開いてhttp://localhost:8080/にアクセスしてみてください。その後Unityエディターにフォーカスを戻さないとスクリプトが動かないのでHTTPレスポンスが返らないので注意してください。
ブラウザにHello from Unity!という文字が出ていれば成功です。