今回は、Unityと外部ツールをノーコードで連携させたい、そんなときに使えるテクニックの話です。 そもそもの発端はこちら。
Unityで、10ms間隔くらいの時系列座標データ(CSV形式)を実時間で再生して、Visual Scriptingでオブジェクトを動かすというのをやりたいんだけど、なにかうまいやり方はないかな?
— アツユキ (@aaa_tu) 2022年2月24日
ひとつ、外部で適当なスクリプトでCSVをパースして、OSCで値を渡す案を思いついたのでとりあえずやってみよう
用語解説
本題に入る前に、主要な用語を簡単に紹介します。
Unity Visual Scripting(旧Bolt)
Unityのビジュアルプログラミング環境で、元々Boltという名前だったサードパーティアセットが本体に取り込まれたものです。
詳しい解説はこの辺りを。
「ビジュアルスクリプティング」だとちょっと長いので、以降「Unity VS」と略します。
Node-RED
IBMが開発したビジュアルプログラミング環境で、データの流れをコントロールして、他のツール・Webサービス・IoT機器とやりとりするような用途に向いています。
今回は、CSVファイルをパースして、一定間隔でUnityに投げるパートを担当してもらいます。
OSC(Open Sound Control)
UnityとNode-REDの通信に使います。
MIDIの進化系(?)、メッセージの自由度が高く、音楽関係に限らず汎用的に使え、扱いも簡単そうなので選びました。
詳しくはWikipediaで。
メッセージをURL的な書式で整理できるので、複数オブジェクトを動かしたいような時に、送信側から動かしたいオブジェクトを簡単に指定したりできるかもというのもあります。
必要な物をインストールする
まずは環境構築です。 Unityは2021.1以降インストール済みで、Unity VSも使える状態になっているものとします。
Unity VSのOscJackVSプラグイン
Unityには標準でOSCを使える機能がないので、自分で追加する必要があります。
そこで、いつも魔法みたいなデモを連発されている、Unity Japanの高橋 啓治郎氏が公開してくれている、「OscJackVS」というプラグインを使います。
※For Boltと書かれていますが、Unity VSでも問題なく動きました。
インストール方法のところに、「スコープドレジストリ」なる未知の概念が出てくるので心折れかけましたが、蓋を開けてみるとプロジェクトのPackageフォルダにあるmanifest.jsonを、GitHubの説明の通り編集するだけだったので、やってみたら超簡単でした。
manifest.jsonを編集すると、Unityエディターを開いた時に、勝手にパッケージをインストールしてくれます。
パッケージマネージャを開いて、OscJackVSが追加されていればOKです。
Unity VSに「OSC」というグループが追加されています。
Node-REDのnode-red-contrib-osc
Node-REDのインストールや使い方ついては割愛します。
ノードの追加画面で「osc」と検索すると、「node-red-contrib-osc」というのがトップに出てくるので、これをインストールすると青いノードが1つ追加されます。
送信受信両用で、入力データから自動判別して、OSCメッセージをエンコード/デコードしてくれます。
このノード自体に通信機能は無いので、UDPやTCP、UARTのノードと組み合わせて使います。
送信側をつくる、CSVファイル→Node-RED→OSC
さて、環境が整ったので、フローを作っていきます。
インプットデータは、移動する2組のオブジェクトの3次元座標が、0.1秒で並んだCSVファイルを用意して、data.csvとしてマイドキュメントに入れておきました。
まずはNode-REDのパートを作ります。 さっそくですが、出来上がりはこのようになります。
フローの順に、各ノードの設定を解説していきます。
Read fileノード
Excelで編集したCSVファイルを使うので、文字コードはShift-JISにします。
CSVノード
インプットされたCSV文字列を、1行づつ切り出して流してくれます。 結果をリストにするかKey-Valueにするか選べるので、今回はKey-Valueで。
Delayノード
送信間隔をコントロールします。 元のデータに合わせて0.1秒に設定します。 間隔のコントロール方法は、データを間引くか、キューに溜めて送るか選べるので、キューに溜める方に設定します。
Templateノード
座標をVector3データとしてUnityに送りたいので、ここで[x,y,z]の形のリストに整形します。 こうしておけば、Unity側は受信したデータをTransformに突っ込むだけで動くはずです。
Splitノード
要素を分解します、ここではObj1とObj2の2つのメッセージに分かれます。 ついでに、OSCノードはmsg.topicをアドレス、msg.payloadをデータとして解釈するので、ここでKeyをtopicに移してやります。
Templateノード
topicをOSCアドレスの形に整形しています、1つ目のTemplateにまとめちゃった方がよかったかも。 /dataは、1階層だと寂しい気がしてなんとなく付けてみました。
OSCノード
これは簡単、繋ぐだけでOKです。
UDPノード
今回はローカルのUnityにデータを送るので、ローカルアドレスを指定します。ポートは空いてればなんでも良いです。今回は8000番にしました。
これでNode-RED側の準備はOK、デプロイしておきましょう。
後半へつづく
あとはUnity側のVSですが、ちょっと長くなってきたので、後半は次の記事に分けることにします。