UnrealEngineをWebSocketのClientにする

わ、前回更新から1年以上経ってしまった....

はじめに

UnrealEngineと書いたのは、UE4・UE5どちらでも大丈夫だと思うため。
というわけで、Go製のWebServerに対してUnrealEngineからWebSocketを経由で通信するサンプルを作りました。

github.com

これの解説を行います。(今回はUE5でいきます)

完成イメージ

プラグインにGameInstanceSubsystemを継承したSubsystemを作成し、その中でWebSocketをServerへつなげて、Serverからメッセージを受け取ります。
それをEventDispatcherにしたので、以下の画像のように使うことができます。

解説

WebServer

github.com

github.com/gorilla/websocketのcommand exampleを参考に書きました。
ここの解説は上記のリンクに譲ろうと思います。

UnrealEngine

まず初めに、.Build.csファイルの依存モジュールにWebSocketsを追加します。

PublicDependencyModuleNames.AddRange(
  new string[]
  {
    "Core",
    // ... add other public dependencies that you statically link with here ...
    "WebSockets", // 例えばこんな感じ
  }
);

続いてSubsystemを作成します。 とりあえずは常時存在してほしいので、GameInstanceSubsystemを継承したクラスで作成します。

headerの完成形はこちら

UnrealWebSock_Sample/WebsocketSampleSubsystem.h at master · crssnky/UnrealWebSock_Sample · GitHub

一部解説していきます。
9行目:IWebSocketを前方宣言します。
11行目:このプラグイン専用のLogカテゴリを宣言します。 12行目:メッセージを受信した際に発火するイベントを宣言します。 22,33行目:UGameInstanceSubsystemのInit, Deinit関数をOverrideします。
25,26行目:最後に受け取ったメッセージを取得する関数を宣言します。
29,30行目:BlueprintからBindできる、メッセージを受信した際に発火するイベントオブジェクトを宣言します。
33~36行目:ソケットオブジェクトのためのイベント関数を宣言します。
38行目:ソケットオブジェクトを宣言します。
39行目:最後に受け取ったメッセージを保持する。


sourceの完成形はこちら

UnrealWebSock_Sample/WebsocketSampleSubsystem.cpp at master · crssnky/UnrealWebSock_Sample · GitHub

void UWebsocketSampleSubsystem::Initialize(FSubsystemCollectionBase& Collection)

Socketオブジェクトを作成し、各種イベントに関数をバインドしていきます。   オブジェクト作成には、WebServerのURIやサブプロトコルwsを入れます。
(本来ならばサブプロトコルはちゃんとするべきですが、テスト用でサーバー側に処理がなく、以下のようなエラー文を経由するため、何かしらを入れておく必要があります)

UE_LOG(LogWinHttp, Warning, TEXT("Attempted to create a WinHttp WebSocket with an empty protocols list"));

設定が終わったら、最後に接続します。

void UWebsocketSampleSubsystem::Deinitialize()

GameInstanceが消える前に、Socketを切断してメモリ領域を開放します。

FString UWebsocketSampleSubsystem::CurrentMessage() const

最後に受け取ったメッセージを取得する関数です。

void UWebsocketSampleSubsystem::OnSocketConnected() const

Socketが接続したときに呼ばれる関数です。
とりあえず確認用に、ログを吐きます。

void UWebsocketSampleSubsystem::OnSocketConnectioinError(const FString& err) const

Socketの接続に失敗したときに呼ばれる関数です。
とりあえず確認用に、Warningレベルで理由を出力します。

void UWebsocketSampleSubsystem::OnSocketClosed(const int statusCode, const FString& reason, const bool wasClean) const

Socketが切断したときに呼ばれる関数です。 とりあえず確認用に、ログを吐きます。

void UWebsocketSampleSubsystem::OnSocketMessageReceived(const FString& msg)

Socketがメッセージを受信したときに呼ばれる関数です。
受け取ったメッセージを保持し、そのメッセージをイベント発行します。

おわりに

本当に、簡単にWebsocketを繋げてメッセージを受信することができました。
ミニマムで言えば、InitializeDeinitializeOnSocketMessageReceivedのみを実装するだけで良いので、本当に簡単です。
何かしらのWebサービスと繋げることも難しくありません。何かの可視化ツールとしても使ってみるのはいかがでしょうか?