凹みTips

C++、JavaScript、Unity、ガジェット等の Tips について雑多に書いています。

Unity から Node.js を裏でこっそり立ち上げてアレコレ出来るアセットをつくってみた

はじめに

先日書いたエントリ(Unity から Node.js を起動時に裏で実行・通信して諸々の処理を肩代わりしてもらう方法考えてみた - 凹みTips)のネタをだれでも使えるようにアセットにしました。起動時に Node.js を裏で実行して面倒なネットワーク周りの処理などを行い、Unity とは OSCWebSocket を通じてやりとりすることで、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 StudioMac なら Xcode で command line tools)が必要です。

仕組み

前も書きましたが図に起こしてみるとこんな感じです。
f:id:hecomi:20140420161520p:plain
なので改変すれば 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 で指定さえすればシェルスクリプトだろうがなんだろうが大丈夫なようです。

サンプルで使用しているライブラリについて

おわりに

面白い体験を如何に早く作るかが問われる時代だと思うので、要所要所に使いやすいツールを使用するのは重要だと思います。ただ別のサーバをいちいち立ち上げるのは面倒...、という時にこういう解決法も有りかな、と思いました。