HoloLens2 × ZIGSIM やーる(Touch)


はじめに

HoloLensアドベントカレンダー2021の8日目の記事です。
今回はZIGSIMを用いて、iPhoneのタッチ操作をHoloLens2にUDP送信し、タップしたら花火を打ち上げてみましょう。

開発環境

  • Windows 10 PC
  • Unity 2020.3.0f1
  • MRTK 2.7.2
  • HoloLens2
  • iPhone 12 Pro
  • ZIG SIM PRO

実装

1.前回の記事を参考にセットアップお願いします

2.ZigSimTouchManager.csを作成し、particleにNoribenFireworksのn_Fireworksをアタッチします

ZigSimTouchManager.cs
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;

#if UNITY_EDITOR
using System.Net;
using System.Net.Sockets;
#else
using System;
using System.IO;
using Windows.Networking.Sockets;
#endif

public class ZigSimTouchManager : MonoBehaviour
{
    int port = 3333;
    Osc.Parser osc = new Osc.Parser();

    public ParticleSystem particle;
    private bool isPlaying = false;
    private string cmd = "";
    private string prevCmd = "";
    private float radius = 0.0f;

    void OnMessage(Osc.Message msg)
    {
        // Debug.LogFormat("{0} => {1}", msg.path, msg.data[0]);
        cmd = msg.path.Split('/').Last();
        if (String.Equals(cmd, "touchradius0")){
            radius = (float)msg.data[0];
            isPlaying = true;
        } else if (String.Equals(cmd, prevCmd)){
            if(isPlaying){
                particle.Play(true);
                isPlaying = false;
            } else {
                particle.Stop(true, ParticleSystemStopBehavior.StopEmitting);
            }
        }
        prevCmd = cmd;
    }

    void Awake()
    {
        particle.Stop();
    }

#if UNITY_EDITOR
    UdpClient udpClient;
    IPEndPoint endPoint;

    void Start()
    {
        endPoint = new IPEndPoint(IPAddress.Any, port);
        udpClient = new UdpClient(endPoint);
    }

    void Update()
    {
        while (udpClient.Available > 0) {
            var data = udpClient.Receive(ref endPoint);
            osc.FeedData(data);
        }

        while (osc.MessageCount > 0) {
            var msg = osc.PopMessage();
            OnMessage(msg);
        }
    }
#else
    DatagramSocket socket;
    object lockObject = new object();

    async void Start()
    {
        try {
            socket = new DatagramSocket();
            socket.MessageReceived += OnMessage;
            await socket.BindServiceNameAsync(port.ToString());
        } catch (System.Exception e) {
            Debug.LogError(e.ToString());
        }
    }

    void Update()
    {
        lock (lockObject) {
            while (osc.MessageCount > 0) {
                var msg = osc.PopMessage();
                OnMessage(msg);
            }
        }
    }

    async void OnMessage(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
    {
        using (var stream = args.GetDataStream().AsStreamForRead()) {
            byte[] buffer = new byte[1024];
            await stream.ReadAsync(buffer, 0, 1024);
            lock (lockObject) {
                osc.FeedData(buffer);
            }
        }
    }
#endif
}

Debug.LogFormat("{0} => {1}", msg.path, msg.data[0]);の部分で、ZIGSIMから次のような値がOSCのメッセージで送られてきます。

/UUID/deviceinfo => iPhone13,3
/ZIGSIM/UUID/touch01 => -0.1383758
/ZIGSIM/UUID/touch02 => 0.3032174
/ZIGSIM/UUID/touchradius0 => 35.03931
/ZIGSIM/UUID/touchforce0 => 0.85

同時にタッチした場合は続けて送られてきます。5本指のタッチまで対応しているようです(N < 5)

/ZIGSIM/UUID/touch{N}1
/ZIGSIM/UUID/touch{N}2
/ZIGSIM/UUID/touchradius{N}
/ZIGSIM/UUID/touchforce{N}

touchradius0を受け取ったら、パーティクルを再生。deviceinfoが連続で受け取ったらタッチしていない状態なのでパーティクルをストップしている感じです。

3.花火のパーティクルは、Noriben Fireworks(花火パーティクル)を使用しています。n_Fireworks以外を非アクティブに、sparclesも黒く映ってしまったので非アクティブにします

Play On AwakeとLoopingのチェックを外しておきましょう

4.デプロイして、ZIGSIMを起動します。下記の設定でStartし、タップして花火が上がれば成功です!

Sensor Setting Start

デモ

お疲れ様でした