はじめに
先日書いたエントリ(Unity から Node.js を起動時に裏で実行・通信して諸々の処理を肩代わりしてもらう方法考えてみた - 凹みTips)のネタをだれでも使えるようにアセットにしました。起動時に Node.js を裏で実行して面倒なネットワーク周りの処理などを行い、Unity とは OSC や WebSocket を通じてやりとりすることで、C# で書くのが面倒な処理を JavaScript(≠ Unity の JS)で肩代わりできるものです。別途サーバを立ち上げる方式よりもアプリを立ち上げれば自動で Node のサーバも立ち上がるので楽、というのが狙いです。
デモ
実行した結果のログなどは簡易的ですが Editor 上で見れるようになっています。
動画では WebSocket サーバの立ち上げと、それを利用した HTML ファイルをホストする処理を行っていて、以下の様なスクリプトを起動時に裏で走らせています。
Assets/StreamingAssets/.node/websocket.js
var http = require('http'); var fs = require('fs'); var server = http.createServer(function(req, res) { fs.createReadStream('./websocket.html').pipe(res); }).listen(8080); var io = require('socket.io').listen(server); io.sockets.on('connection', function (socket) { socket.emit('server/hello', { from: 'server' }); socket.on('browser/move', function (data) { io.sockets.emit('browser/move', data); }); });
デモでは WebSocket でマウス座標送っているだけですが、Twitter のストリーム取ってきて整形したデータを渡すとかすれば楽に色々出来ると思います。
ダウンロード
unitypackage を開いて下さい。原因は不明ですが Mac でフリーズする時がある気がします(結構します)。。強制終了した際は、前回の Node.js のプロセスが生きているかもしれないので ps コマンドで調べて kill して下さい。。Win 版は安定していると思います。
使い方
NodeJs スクリプトを空のオブジェクトにアタッチすれば、Script Path で指定した js(StreamingAssets/.node/ 以下のパス)を裏で実行します。サンプルを実行するためには npm からモジュールをインストールしてビルドする必要があるので、Assets/StreamingAssets/.node 以下でコマンドを実行して下さい。
$ cd Assets/StreamingAssets/.node
$ npm install
ただ、ビルドには Node.js の環境とビルド環境(Win なら Visual Studio、Mac なら Xcode で command line tools)が必要です。
仕組み
前も書きましたが図に起こしてみるとこんな感じです。
なので改変すれば Node.js じゃなくて何でも動かしておけると思います。
隠しフォルダとビルドについて
.hogehoge という "." プレフィックスがつくディレクトリは Win でも Mac でも Unity によってハンドルされません。そこで、「.node」というディレクトリを Streaming Assets 以下に作り、そこに js や Node.js のモジュールを入れます。これによって Unity に js がコンパイルされ、パースエラーで怒られる、といったことがなくなります。
しかしながら、ビルド時にこれが問題になってきます。Windows では問題なく Streaming Assets の中身がビルド後のディレクトリへすべてコピーされるのですが、Mac だとコピーされないようです。そこでビルドプレイヤーパイプラインを利用して、ビルド後のポストプロセスとして .node ディレクトリをビルド後の Streaming Assets ディレクトリへコピーするようにしています。
Editor/PostprocessBuildPlayer
#!/usr/bin/perl my $installPath = $ARGV[0]; my $node_dir = "Assets/StreamingAssets/.node"; my $target_dir = "$installPath/Contents/Data/StreamingAssets/."; system "cp -r $node_dir $target_dir";
上記では Perl でコピーしてますが、Unity からは単に実行するだけなので Shebang で指定さえすればシェルスクリプトだろうがなんだろうが大丈夫なようです。
サンプルで使用しているライブラリについて
- WebSocket: GitHub - NetEase/UnitySocketIO: socket.io client for unity3d.
- Socket.IO でやりとり出来る便利なライブラリです。ただ Unity 側から Emit 出来ないようなので、双方向にやりとりしたい場合は Node.js 側は socket.io の代わりに ws を使って websocket-sharp でやりとりするのが良いと思います。
- OSC: https://github.com/keijiro/unity-osc
- OSC のレシーバーです。同じく Unity からの情報をサーバには送れないので、送りたい時は
おわりに
面白い体験を如何に早く作るかが問われる時代だと思うので、要所要所に使いやすいツールを使用するのは重要だと思います。ただ別のサーバをいちいち立ち上げるのは面倒...、という時にこういう解決法も有りかな、と思いました。