UnityOSC で OSC を受信する / MaxMSP で送信する

Unityのロゴ。

ここでは MaxMSP を使って OSC を送信し、UnityOSC を使って Unity で受信する方法を解説します。 このコンテンツは「UnityOSC で OSC を送信し MaxMSP で受信する」の続きです。 諸々の説明については前回分で説明していますので、先に目を通していただいたほうが良いと思います。

UnityOSC の設定

UnityOSC に含まれる OSCHandler.cs を受信用に書き換えます。該当するコードは次の通りです。 (オリジナルの UnityOSC からわずかに改変しています。)

CreateClient は Unity から送信する場合に使います。今回は CreateServer を使います。 名称から目的が分かりにくいので注意してください。

引数は識別子とポート番号です。

public void Init(string id, string serverIp, int serverPort)
{
	//Initialize OSC clients (transmitters)
	//Example:		
	//CreateClient(id, IPAddress.Parse(serverIp), serverPort);

	//Initialize OSC servers (listeners)
	//Example:
	CreateServer(id, serverPort);
}

OSC を受信するスクリプト

OSC を受信するスクリプトを実装します。ここでは OSCController.cs とします。詳細はコードを参照してください。 まずは UnityOSC の機能を使うために、先に設定した OSCHandler を初期化します。 OSCHandler はシングルトンで実装されている点に注意します。

void Start ()
{
	OSCHandler.Instance.Init(this.serverId, this.serverIp, this.serverPort);
}

今回は、OSC は常に送られてくる可能性があると想定して、Update メソッド内で受信を確認します。

OSCHandler.Instance.UpdateLogs() で OSC の受信を確認します。 受信した OSC は、OSCHandler.Instance.Servers から確認することができます。

private long latestTimeStamp = 0;
…
void Update()
{
    OSCHandler.Instance.UpdateLogs();

    foreach (KeyValuePair<string, ServerLog> item in OSCHandler.Instance.Servers)
    {
        if (item.Value.packets.Count == 0)
        {
            continue;
        }

        int latestPacketIndex = item.Value.packets.Count - 1;

        if (this.latestTimeStamp == item.Value.packets[latestPacketIndex].TimeStamp)
        {
            continue;
        }

        this.latestTimeStamp = item.Value.packets[latestPacketIndex].TimeStamp;

        Debug.Log("Receive : "
              + item.Value.packets[latestPacketIndex].TimeStamp
              + " / "
              + item.Value.packets[latestPacketIndex].Address
              + " / "
              + item.Value.packets[latestPacketIndex].Data[0]);
    }
}

詳細な方法はコードを参照していただくとして、item.Value.packets[latestPacketIndex].TimeStamp, item.Value.packets[latestPacketIndex].Address, item.Value.packets[latestPacketIndex].Data でデータを取得することができます。

重要な点は、TimeStamp を確認している点です。 UnityOSC は最後に受信した OSC の情報を常に維持する使用になっています。 つまり、Queue(キュー) 構造にはなっていないため、最新のデータを参照してもそのデータは破棄されません。

したがって、あらたなデータを受信したかどうかを確認するためには、TimeStamp を監視する必要があります。

MaxMSP から OSC を送信する

Max MSP で作ったパッチ。udpsend オブジェクトを使って、UDP で OSC を送信している。

受信するときのものと比較して、もう少し高度な機能を追加しました。ボタンを押すと、UDP で OSC を飛ばすようにしています。 MaxMSP で UDP を送信するときは udpsend オブジェクトを作ります。引数はアドレスとポート番号です。 ここで指定するポート番号は、Unity で指定したポート番号と一致させる必要があります。

今回は prepend オブジェクトも追加しています。prepend は引数の値を、受信したメッセージの後ろに追加して、次のオブジェクトに流す役割を持ちます。 文字通りです。同種のオブジェクトに append がありますが、こちらは受信したメッセージの前に追加します。

ここでは数値を与える numbers オブジェクトの次に prepend オブジェクトが与えられ、その引数には /sample が指定されているので、 最終的な出力は、/sample 108 となります。

このメッセージは一番上に繋げられた Button オブジェクトを押すまで流れて来ない点に注意してください。 (あるいは Numbres オブジェクトの値が変更されるまで)

Button オブジェクトをマウスによってクリックできるようにするためには、MaxMSP ウィンドウの左下にある鍵のマークをクリックし、 編集を固定する必要があります。

Unity で受信を確認する

今回は Unity ではデバッグメッセージとして受信した内容を表示しています。

Receive : 636074783614781163 / /sample / 108
UnityEngine.Debug:Log(Object)

ここで、Unity は標準では非アクティブ時にはすべての更新が停止される点に注意してください。 MaxMSP から OSC を送信しても Unity 側が更新されない限り、デバッグメッセージの受信は確認できません。 (MaxMSP がアクティブウィンドウになり、Unity が非アクティブウィンドウになるため)

この問題を解決するためには、MaxMSP から OSC を送信した時点で、Unity の画面をクリックしてアクティブウィンドウを切り替えるか、 あるいは Unity を非アクティブ時にも更新するようにします。

[Unity > ProjectSettings > Player(Settings)] の項目、[Run In Background*] を有効にすると、Unity は非アクティブ時にも更新されるようになります。

MAX/MSP から複数の値を送信する : ヒント

OSC で送信する値は、1 つとは限りません。複数の値を送信するときは、次のようにします。

MAX/MSP で複数の値を OSC で送信するバッチ。