UnityOSCではまる

  • 34
    Like
  • 0
    Comment
More than 1 year has passed since last update.

oFなどの外部プログラムからOSCを受け取ってUnityを動かす場合、UnityOSCが有名っぽいので使ってみたがハマったのでメモ。

同じイベントを拾い続ける

マニュアルを読む限り、Update()の内部でOSCHandler.Instance.UpdateLogs()を呼んで新しいメッセージを取得しろということらしいが、内部的にはキューになっておらずUpdateLogs()を呼んでも古いメッセージが残ったままになっているので新着メッセージがどれだか分からない。Timestampを使おうと思っても全部0になっているので比較できない。

(このへんはIssueとして取り上げられている模様)

メッセージをこぼす

内部構造上UpdateLogs()で更新されるメッセージは最後に到着した1つだけなので、更新の間にメッセージが複数到着すると最後のメッセージ以外は取りこぼす。センサーデータとかだとこれは致命的。

OSCMessageとOSCBundle

ofxOscSenderを使ってメッセージを送ると、単発のメッセージでもOSCBundleとして投げられるっぽいので、受け手側はふつうのOSCMessageとして受けようとするとはまる。

対策

本体直してプルリクしろよという話なのですがとりあえずのワークアラウンドとして。

UnityOSC側:

OSCHandler.cs
public class OSCHandler : MonoBehaviour
{
    public event PacketReceivedEventHandler PacketReceivedEvent;

    void OnPacketReceived(OSCServer server, OSCPacket packet)
    {
        // パケット受信時にイベントを投げる
        PacketReceivedEvent(server, packet);
    }

使用するController側:

OSCController.cs

using UnityEngine;
using System.Collections;
using UnityOSC;

public class OSCController : MonoBehaviour {

    private Queue queue;

    void Start () {
        queue = new Queue();
        queue = Queue.Synchronized(queue);

        OSCHandler.Instance.Init();
        // パケット受信時のイベントハンドラを登録
        OSCHandler.Instance.PacketReceivedEvent += OnPacketReceived;
    }

    void OnPacketReceived(OSCServer server, OSCPacket packet) {
        // 来たパケットをキューに積んでおく
        queue.Enqueue(packet);
    }

    void Update () {
        while (0 < queue.Count) {
            OSCPacket packet = queue.Dequeue() as OSCPacket;
            if (packet.IsBundle()) {
                // OSCBundleの場合
                OSCBundle bundle = packet as OSCBundle;
                foreach (OSCMessage msg in bundle.Data) {
                    // メッセージの中身にあわせた処理
                }
            } else {
                // OSCMessageの場合はそのまま変換
                OSCMessage msg = packet as OSCMessage;
                // メッセージの中身にあわせた処理
        }
    }
}

一応これでopenFrameworksからUnityへのメッセージ送信はうまく行きました。