記事の目次

    今回は、通信プロトコルOSCを、Unityで使えるようにセットアップします。

    TEXT_高田稔則 / Toshinori Takata(Codelight
    EDIT_小村仁美 / Hitomi Komura(CGWORLD)

    <1>UnityでOSCを使えるようにする

    こんにちは、高田です。いままでいくつかのセンサの値を取る例を紹介してきました。こういったセンシングのプログラムを毎回コンテンツに組み入れるのは多少手間がかかります。またセンサとコンテンツで処理PCを分ける必要がある、などの理由でセンシング部分と演出部分でプログラムを分離する場合があります。弊社でもGUI絡みの部分はUnityのuGUI、演出部分は別PCで稼働するTouchDesignerで制作するといったことを行なっています。今回はそのような状況でよく使われる通信プロトコルOSC(Open Sound Control)を紹介します。OSCは、異なるアプリケーションやハードウェア間でのデータ通信を行うための規格です。

    OSCに関しては下記の田所 淳さんのエントリにわかりやすく書いてあります。2010年の記事ですが仕様は変わっていないので参考にするのに問題はありません。OSCの最初の仕様が出たのが2002年ですから十分枯れたフォーマットだと言えますし、多くのアプリケーションやハードウェアで標準的に実装されています。

    openFramewoks - OSC (Open Sound Control) を利用したネットワーク連携
    https://yoppa.org/ma2_10/2279.html

    残念ながらUnityには標準でOSCのライブラリが用意されていません。そのかわりたくさんの実装が公開されているため、自分の使いやすいものを選ぶことができます。今回はUnity Japanの高橋 啓治郎さんがGitHubで公開している「OscJack」を利用してみます。

    GitHub - keijiro/OscJack: Lightweight implementation of OSC server/client in C# (Unity)
    https://github.com/keijiro/OscJack

    zipをダウンロードしAssets/OscJackフォルダをUnityのAssetsフォルダにインポートします。


    これでUnity側の準備は完了です。OSCを試してみるのに一番手軽なのは、iOS/Android用のアプリである「TouchOSC」を使う方法です。

    TouchOSCをインストールした端末を、通信したいPCと同じネットワークに接続します。TouchOSCを起動するとCONNECTIONSセクションにOSC:192.168.1.100などIPアドレスが書いてある部分があります。これをタッチしてHost部分にデータを送りたいIPを送信したいPCのIPアドレスを指定して下さい。Port(outgoing)は送信時に使うポート番号、Port(incoming)は受信時のポート番号です。

    UnityのWindowからOSC Monitorを起動します。



    TouchOSCでデータを送ってみます。以下のようにデータが送られてきた人もいると思いますが、何も起こらない人もいると思います。

    原因を考えてみます。データが送られてこないほとんどの理由は、Windowsファイアウォールで遮断されているからです。Windowsの設定から「ネットワークとインターネット」を開きます。


    次に「ファイアウォールとネットワーク保護」の内容を確認して下さい。「ドメインネットワーク」、「プライベートネットワーク」、「パブリックネットワーク」のいずれかがアクティブになっていると思います。アクティブになっているネットワークが自分が接続されているものです。


    どのネットワークがアクティブになっているかを確認して、「詳細設定」を開きます。筆者が動かしているのはUnity 2019.1.6.f1のEditorなので該当するプログラムを探してみると、パブリックの接続がブロックされています。


    プロパティを開き、「接続を許可する」にチェックを入れOKします。

    これでパブリックでも接続が許可されました。もう一度データを送ってみると、モニタに表示されるようになったと思います。


    ネットワークを介した連携を行うことは多いですが、上手く接続されないこともままあります。そのときはまずWindowsファイアウォールの設定を見直してみて下さい。

    次ページ:
    <2>入力値をUnityのライトに反映させる

    [[SplitPage]]

    <2>入力値をUnityのライトに反映させる

    続いて、TouchOSCのLAYOUTをMix 16にします。


    一番左のフェーダを動かしてみると、OSC Monitorには
    /1/fader1 0.4723752
    などデータが送られてきます。

    この値をUnityのライトに反映させてみましょう。スクリプトは以下のようになります、これをライトゲームオブジェクトにアサインしてTouchOSCでデータを送ると、連動してライトの色と向きが変化します。

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using OscJack;
    
    public class OscSample : MonoBehaviour
    {
        private OscServer _server;
        private Color _color;
        private Vector3 _rot;
        private Light _light = null;
    
        // Start is called before the first frame update
        void Start()
        {
            _light = GetComponent<Light>();
    
            _server = new OscServer(8000); // Port number
    
            _server.MessageDispatcher.AddCallback(
                "/1/fader1",
                (string address, OscDataHandle data) =>
                {
                    _color.r = data.GetElementAsFloat(0);
                }
            );
            _server.MessageDispatcher.AddCallback(
                "/1/fader2",
                (string address, OscDataHandle data) =>
                {
                    _color.g = data.GetElementAsFloat(0);
                }
            );
            _server.MessageDispatcher.AddCallback(
                "/1/fader3",
                (string address, OscDataHandle data) =>
                {
                    _color.b = data.GetElementAsFloat(0);
                }
            );
            _server.MessageDispatcher.AddCallback(
                "/1/xy",
                (string address, OscDataHandle data) =>
                {
                    _rot.x = data.GetElementAsFloat(0) * 180f;
                    _rot.y = data.GetElementAsFloat(1) * 360f - 180f;
                }
            );
        }
    
        private void OnDestroy()
        {
            _server.Dispose();
        }
    
        // Update is called once per frame
        void Update()
        {
            _light.color = _color;
            _light.transform.eulerAngles = _rot;
        }
    }
    

    このしくみを応用すると、様々なセンシング機材を利用してコンテンツを組むことができます。せっかくなので、もう少し雰囲気の出る機材を使ってみましょう。実際の照明制御には「DMX」と呼ばれる信号を使います。このようなコントローラを利用します。


    背面にはDMX out端子があり、対応ライトに接続することで色などを制御することができます。

    これをUnityに接続してみます。DMX信号をPCで取り扱う場合にとても便利な「DoctorMX」という機材を使います。


    DoctorMXをDMXコントローラに接続し、DoctorMXはPCにUSBで接続するとDMXコントローラの値がPCで取得できるようになります。このコントローラは3チャンネルしか信号を出力できませんが、DoctorMX自体は512チャンネルまで同時出力が可能です。


    Unityとの連携はとても簡単です。DoctorMXの[ウインドウ→機能を追加→OSC]を選びます。


    表示されたダイアログの値を以下のように設定します。

    これで、8000ポートにdmx信号がOSCとして送られます。しかし、OSC Monitorを見ると「/dmx」としか表示されていません。

    これはDoctorMXからBlob(Block of binary data)型でデータが送られてきているのに、OscJackではBlob型の入力に対応していないので値が無視されるからです。BlobとはRAWデータと考えれば良いです。

    そこで今回はhecomiさんが公開しているOSC実装を使ってみます。

    Unity 向けの OSC 実装を作ってみた - 凹みTips
    http://tips.hecomi.com/entry/2017/08/20/193823

    以下のようなコードで入力値をライトの色に反映させることができます。DMXのスタートコードが先頭に入るので、要素1がチャンネルの1に対応します。

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using uOSC;
    
    public class OscSampleDrMX : MonoBehaviour
    {
        // Start is called before the first frame update
        void Start()
        {
            var light = GetComponent<Light>(); 
    
            var server = GetComponent();
            server.onDataReceived.AddListener((message) => {
                if (message.address == "/dmx")
                {
                    var dmx = (byte[])message.values[0];
                    light.color = new Color(dmx[1] / 255f, dmx[2] / 255f, dmx[3] / 255f);
                }
            });
        }
    
        // Update is called once per frame
        void Update()
        {
        }
    }
    

    反対に、Unity内でのライト情報を実際のDMX対応ライト機器に反映させることも可能です。このしくみを利用するとUnity内のライトデータと実際のライトを連動させる演出なども作ることができます。OSCを使っての連動は、色々遊べますので試してみて下さい。

    今回はデータの共有方法としてOSCを紹介しました。次回は映像の共有方法であるSyphoneSpoutNDIなどを紹介したいと思います。



    Profile.

    高田稔則/Toshinori Takata(Codelight)
    Codelight株式会社 代表取締役・インタラクションエンジニア
    フリーランス、株式会社TBSテレビ等で映画CG制作、株式会社ソニー・コンピュータエンタテインメント(現 ソニー・インタラクティブエンタテインメント)でPS4のOSD開発などを経て2006年にCodelight株式会社を設立。インタラクティブコンテンツの制作を中核として、製造業向けのプロトタイプ開発なども行う
    www.codelight.co.jp