UnityのOSCライブラリであるUnityOSCについて調べました。
jorgegarcia/UnityOSC: Open Sound Control (OSC) C# classes interface for the Unity3d game engine
Githubリポジトリ内で言及されていますが、UnityOSCは現在開発されておらず、他のOSCライブラリの使用が推奨されています。
本記事の内容はUnityバージョン2021.2.9f1、エディタ上でのみ検証しています。
インストール
Githubリポジトリをクローンまたはダウンロードし、srcディレクトリ内のファイルをUnityプロジェクトのAssetsディレクトリ以下の任意の場所にコピーします。
使い方
Githubリポジトリのdocsディレクトリ内にマニュアルとAPIリファレンスがあります。
OSCの受信
UnityOSCでOSCを受信するにはOSCHandler
を使う方法とOSCReceiver
を使う方法の2つがあります。OSCReceiver
の方が使用が簡単なため、ほとんどの場合にはOSCReceiver
を使う方がいいと思います。
OSCHandlerを使う方法
OSCHandler
からOSCServer
を取得してOSCを受信します。OSCServer#PacketReceivedEvent
にOSC受信時に実行するメソッドを登録します。このメソッドはメインスレッド外で実行されるのでほとんどのUnity APIは使用できません。Unity APIを使用するためにはメッセージのキューイングなどを自分で実装する必要があります。
using UnityEngine;
using UnityOSC;
public class UnityOscHandlerReceiveSample : MonoBehaviour
{
[SerializeField] string serverId = "local";
[SerializeField] int port = 8000;
OSCServer oscServer;
void Awake()
{
OSCHandler.Instance.Init();
oscServer = OSCHandler.Instance.CreateServer(serverId, port);
}
void OnEnable()
{
oscServer.PacketReceivedEvent += OscReceivedCallback;
}
void OnDisable()
{
oscServer.PacketReceivedEvent -= OscReceivedCallback;
}
void OscReceivedCallback(OSCServer sender, OSCPacket packet)
{
if (packet.IsBundle())
{
var bundle = (OSCBundle)packet;
foreach (object data in bundle.Data)
{
LogOscMessage((OSCMessage)data);
}
}
else
{
LogOscMessage((OSCMessage)packet);
}
}
void LogOscMessage(OSCMessage message)
{
if (message.Address == "/UnityOSC/sample")
{
Debug.Log($"UnityOSC receive: {(string)message.Data[0]} {(float)message.Data[1]} {(int)message.Data[2]}");
}
}
}
OSCReceiverを使う方法
OSCReceiver
を使う方法です。OSCバンドルの展開とOSCメッセージのキューイングをOSCReceiver
がしてくれるので、OSCHandler
を使う方法よりも実装が単純になります。OSCReceiver#hasWaitingMessages
でキューイングされたメッセージがあるか確認し、OSCReceiver#getNextMessage
でキューイングされたメッセージを取得します。
using UnityEngine;
using UnityOSC;
public class UnityOscReceiverSample : MonoBehaviour
{
[SerializeField] int port = 8000;
OSCReciever oscReceiver;
void OnEnable()
{
oscReceiver = new OSCReciever();
oscReceiver.Open(port);
}
void OnDisable()
{
oscReceiver.Close();
oscReceiver = null;
}
void Update()
{
while(oscReceiver.hasWaitingMessages())
{
var message = oscReceiver.getNextMessage();
if (message.Address == "/UnityOSC/sample")
{
Debug.Log($"UnityOSC receive: {(string)message.Data[0]} {(float)message.Data[1]} {(int)message.Data[2]}");
}
}
}
}
OSCHandler
を使う方法でもOSCReceiver
を使う方法でもOnDisable
を呼び出すタイミングで以下のエラーがでますが、UnityOSC側を修正せずに対応するのは難しそうでした。
Exception: Can't create server at port 8000
OSCの送信
OSCHandler#SendMessageToClient
でOSCを送信します。
using System.Collections.Generic;
using System.Net;
using UnityEngine;
public class UnityOscHandlerSendSample : MonoBehaviour
{
[SerializeField] string clientId = "local";
[SerializeField] string ipAddress = "127.0.0.1";
[SerializeField] int port = 8080;
void Start()
{
OSCHandler.Instance.Init();
OSCHandler.Instance.CreateClient(clientId, IPAddress.Parse(ipAddress), port);
}
void Update()
{
OSCHandler.Instance.SendMessageToClient<System.Object>(clientId,
"/UnityOSC/sample", new List<System.Object>(){ "hoge", 123.456f, 100 });
}
}
送信する値が1つの場合には次のように、SendMessageToClient
のオーバーロードメソッドを使用します。
// send single value
OSCHandler.Instance.SendMessageToClient<float>(clientId, "/UnityOSC/single", 123.456f);
モニタリング
Menu > Window > OSC Helper
でOSC Helper
ウィンドウを表示します。OSC Helper
ウィンドウでOSC Handler
によるOSCの送受信をモニタリングすることができます。
まとめ
UnityOSCの使い方について解説しました。
他のOSCライブラリと比較して機能的にシンプルなので割と容易に使い方を理解できますが、単純なOSCの送受信でも自分でスクリプトを書く必要があります。
UnityOSC自体は既に開発が停止しているので、uOSCなど簡易にOSCを利用できる他のライブラリの使用を検討してもいいと思います。