Blog

UnityアプリケーションをWindowsアプリケーションから制御する

以下のようなWindowsアプリケーションから、UnityアプリケーションをNamedPipeを介して制御する方法を紹介する。なおソースコード全体はGitHubのリポジトリに置いてある。

Windows側

Unity側にメッセージを送るときには、NamedPipeのクライアントであるIPCクラスを利用する。以下では、ViewにバインドされたプロパティでUnity側にメッセージを送っている。SendはUnity側からの応答を返す。

Unity側

まず第一に、NamedPipeをUnityで利用するには、Player SettingsでApi Compatibility Levelを.NET 4.xにする必要があることに注意してほしい。エディターのプレイモードなら.NET Standard 2.0でも動くが、standalone playerでエラーになってしまう。

Unity側ではこちらのIPCクラスを使用する。以下にNamedPipeの待ち受けを行うReceiveメソッドの定義を示す。

UniTaskを用いた非同期メソッドになっている。コルーチンよりもUniTaskのほうがずっと簡単に非同期操作を実装できる。ここでNamedPipeの非同期系(~Async)のメソッドを用いていないのは、Unityには非同期系のメソッドが実装されていないからだ。コンパイルは通るが実行時にエラーになるので注意してほしい。

以下は、Windowsからのメッセージを処理するControllerクラスである。すべてのシーンに空のGameObjectを配置して、Controllerオブジェクトをコンポーネントとして張り付ける。

AwakeでControllerをDontDestroyOnLoadを使用して、シーンが変わったときにControllerが破棄されないようにしている。そうしないとLoadSceneでシーンを切り替えた後にWindows側に応答を返せなくなる。Startではメッセージのハンドラーを与えてIPC.Runを実行する。

OnApplicationQuitではIPC.Closeを呼んでいる。IPC.Closeは、以下のように自身のNamedPipeに接続して、IPC.Receiveの待ち受け状態を解除する。そうしないと、エディターのプレイモードで実行したときに待ち受けたスレッドが残り、エディターが終了しなくなる。

上で紹介した2つのIPCクラスは私が独自に実装したものだ。UnityでNamedPipeを使う記事はどれも実験レベルで、現実のアプリケーションで問題なく動くように作られていなかったので、自分で実装することにした次第である。

C#でロックフリーなメモリープールを自作する

基本的にシングルスレッドでしか使わないライブラリを、速度を落とさずにスレッドセーフにするために、ロックフリーなメモリープールを自作した話を紹介する。この記事はC# その2 Advent Calendar 2020の18日目の記事である。

"C#でロックフリーなメモリープールを自作する" の続きを読む

[Unity] Physics.OverlapCapsuleの使い方

Capsule and Cube Collider

このようにCapsule Colliderに重なってる2つのColliderを取得したいときは、Physics.OverlapCapsuleを使うとよい。このメソッドにCapsule Colliderの位置と大きさを与えると、重なっているColliderがすべて返る。RigidbodyをKinematic TriggerにしてOnTriggerEnterをハンドルして取得することもできるが、こちらのほうが手軽である。

"[Unity] Physics.OverlapCapsuleの使い方" の続きを読む

厳格なJSONパーザーの作り方

僕の作ったJSONパーザーのDynaJsonはとても厳格にできている。RFC 8259に準拠しているものはすべて受理するし、そうでないものは二つの例外を除きすべて受理しない。

受理する例外は、ケツカンマと02-02のような0で始まる数字である。前者を受理するのは実用性のためであり、後者を受理するのはDynamicJsonとの互換性のためである。

JSONの文法はとても単純だが、不用意にパーザーを実装するとRFCに準拠したJSONを受理しなかったり、非準拠のものをエラーにできなかったりする。パーザーを実装する際の地雷ポイントはParsing JSON is a Minefieldによくまとまっている。

"厳格なJSONパーザーの作り方" の続きを読む

Docker for WindowsでWindowsの任意のフォルダをコンテナにマウントする

普通にdockerを使っている場合は、docker run -v /source:/destinationとするとコンテナホストの/sourceをコンテナの/destinationにマウントして、コンテナからアクセスできる。

では、Docker for WindowsでC:\Sourceをコンテナの/destinationにマウントしたいときはどうするか。VMホストのC:\Sourceをコンテナの中に直接マウントすることは当然できない。

まず最初に、 docker-machineでVMを作成するときにC:\Sourceを共有フォルダとして設定する。共有フォルダはVirtualBox deriverの--virtualbox-share-folderオプションで以下のように指定できる。

docker-machine create --driver virtualbox --virtualbox-share-folder=C:\Source:Source

"Docker for WindowsでWindowsの任意のフォルダをコンテナにマウントする" の続きを読む