AYU MAX

プログラミングとか作ったもの

ObjectDelivererへ共有メモリプロトコル追加

共有メモリ機能

自作のUE4用ライブラリObjectDelivererに共有メモリプロトコルを追加実装しました。

これにより、従来から実装済みのTCP/IP, UDPに加えて共有メモリを使ったデータ転送が行えます。 ただし共有メモリはWindows Onlyです。。。

使い方

ObjectDelivererのプロトコルとして実装してあるため、ObjectDelivererManagerのStartメソッドに渡すプロトコルを切り替えるだけで使用できます。

deliverer->Start(UProtocolFactory::CreateProtocolSharedMemory("memory_test", 1024),
                 UPacketRuleFactory::CreatePacketRuleSizeBody());

CreateProtocolSharedMemoryには共有メモリ名とメモリサイズを渡します。 この2つはデータのやり取りを行う相手と同じ値である必要があります。

仕様

データの送受信プロトコルとして使うため、作成した共有メモリの中身は定期的にポーリングしています。 ただし毎回データアクセスを行うと処理負荷が上がるため、以下のような仕組みで対応しています。

ブロック サイズ(byte) 内容
カウンター 1 データの書き込みを行う度にインクリメント
サイズ 4 データ部のサイズ
データ n 書き込まれるデータ

定期的なポーリング時はまず共有メモリの先頭1byteを読み込んで、前回読み込み時とカウンタの値が異なっているかをチェックします。

異なっていれば新しいデータが書き込まれていると判断して、次の4byteを読み込みデータサイズを確認した後データ本体を読み込みます。

そのためObjectDelivererを使ってないプロセスと共有メモリを使ったやり取りをする場合は、この仕様に合わせる必要があります。

サンプル

今回作成した共有メモリプロトコルを使って、以下のムービーのようなサンプルを作りました。

WPFで作ったアプリケーションに毎フレーム自分のウィンドウの表示内容を共有メモリに書き込ませ、UE4側ではObjectDelivererを使ってデータを受信します。

受信したデータ(ピクセルバッファ)を使ってテクスチャの中身を更新して、UE4の表示側をWPF側にミラーリングしています。

共有メモリのため同じマシンに2つのアプリケーションがないと使えませんが、パッと見た感じ遅延もなく同期できています。

参考までにここで作成したWPFアプリは↓です。

github.com

課題

長時間上記ミラーリングしていると共有メモリの読み込み時にUObject::ProcessEventの!IsUnreachable()のチェックにひっかかり落ちてしまう現象がでちゃってます。

これが治らないと使えないなー。

暫定ですが、BlueprintNativeEventを使っているところを全て取り除くことで治りました。 ただしこれではBlueprintでオーバーライドできなくなるので、そのあたりまた検討します。