"そこ"から這い上がるブログ

プログラミングと電子工作が趣味でそこら辺のことを備忘録的に書きつつ這い上がっていこうといったブログ。そこ這い。

HoloLensとUWPアプリでUDP通信したかった話(した話)

もう何十日ぶりかわからない更新です。
最近はゲームAIの勉強とHoloLens、時々ステレオカメラという日々です。

さて、最近のHoloLens開発ですが、意味不明なエラーに苦しめられています。
もちろん自分が知識不足なのは重々承知していますが、それにしても!多い……HoloLens自体まだ開発者向けである上、あの値段ですから動かしている人の情報が少ないですね。こんなブログでも同じように困っている人の助けになれば幸いです。

まぁそれはさておき、本題です。

現在開発中のHoloLensアプリで、UDP通信をする必要が出てきまして、苦しみながらもなんとかそれができたのでまとめようと思った次第であります。

 まず最初にHoloLensのアプリ関してなのですが、HoloLensはWindowsが動いているということは皆さんご存知だと思います。ただそこで動いているWindowsはPCで動いているようなものではなく、タブレットやWindowsPhoneなどで動いている方に近い(同じ?)なようです。
そのため動いているアプリも拡張子.exeのアプリケーションとは違っていて、UWP(Universal Windows Platform)で動くアプリケーションなのですね。PC用のWindowsしか使っていない人でも見たことあると思います。ウィンドウの縁がないやつがそれだったりします。Windowsストアで配布しているソフトはみんなそうなんですかね(WindowsストアアプリとUWPアプリの違いはあるのかもしれませんが)。
で。HoloLensで動かしているUWPアプリと別の端末で動かしているUWPアプリでUDP通信をしたい。というのが本題です(前置きが長い)。
紛らわしいので前者をHoloLensアプリ、後者をUWPアプリという風に呼ぶことにします。

HoloLensアプリの開発のメインはUnityとマイクロソフトGitHubで公開しているHoloToolkit-Unity、そしてVisualStudioの組み合わせが一般的だと思います。動いているのはUWPアプリなのでVisualStudioだけでももちろん作れますが、HoloLensの機能を生かしていくには、あの組み合わせがやっぱいいんだと思います。なんだかんだ言ってUnityが簡単にしてくれているので。
今回の環境も同じで

  • Unity 5.6.2f1 (.Net4.6)
  • HoloToolkit-Unity v1.5.7.0
  • VisualStudio 2017

 以上の構成でお送りいたします。

なぜUDP通信をする必要があったのか、Unity同士ならUNETをはじめとするあらゆるネットワーク通信があるのですが、今回は片方がUnityを使わないUWPアプリであった、自分が前にUnityとC++のアプリでUDP通信をしたことがあったからなどが理由ですが。後者は正直なんの役にも立ちませんでした。
面倒なのが、UnityでうごいてもHoloLensでは動くとは限らない(!?)という問題がある為です。今回苦労した点のほとんどはこれにつきます。いやほんと……

HoloLensアプリをUnityで作ったことがある方はご存知かと思いますが、UnityでHoloLensアプリを作るためにはUWPアプリ(Windowsストアアプリ)を対象にビルドしないといけません。

f:id:knasa:20170707003656p:plain

Unityでビルドすると.slnファイルが書き出されて、そのソリューションファイルをVSで開いてビルドするという二段階のビルドを必要とします。大抵の場合(多分)はUnityで動けば何も問題なくビルドできるわけですが、Unityで通ってもVSで通ってもVSではダメ(その逆もしかり)というのが今回時間をごっそり持ってかれた半分の原因です。もう半分は知識不足です。
HoloToolkit使ってんならボタン1つでUnityのビルドからHoloLensにアプリを入れるまでやってくれるでしょ?という声が聞こえてきますし、自分もそうしたいのですが、なぜかまとめてやるとできません……まぁそれでも一つ一つのビルドはHoloToolkitでできるので、VSを立ち上げてビルドする必要はないのですが、Debugログを確認しながらやりたかったのでVSを立ち上げながらやりました。最終的にはVSを立ち上げる必要があったという結果になりました。

ようやく中身の話をします。まず受信側(HoloLensアプリ)のコード

gist.github.com

#define UNITY_EDITOR

 でUnityエディター上とそれ以外(UWP)で分けています。おかげでUWP側のコードはVSの機能が全く効きません……BuildSettingsのDebugging / Unity C# ProjectsをチェックしておけばUnityでビルドした後の.slnからスクリプトを編集できるはずなんですが、うちの環境ではエラー祭りになるのでチェックを入れていません……解決策があったら教えてください。

Unity側ではUdpClientを使っていて、こちらは探すと沢山出てくると思います。ただこれがUWP側ではビルドが通らない(Unityがはいた.slnがビルドできない)のです。
そのためUWPでも使えるDatagramSocketを使うことになります。そしてこれはUnityでビルドが通らない(Windowsに依存してるから)……
そしてこのコードをビルド&ビルドでいざ実行すると……UDP受信できない!

デバッガーの出力にはこんな文字が

Exception thrown: 'System.UnauthorizedAccessException' in Assembly-CSharp.dll

WinRT information: At least one network capability is required to create a socket.

検索すると、なるほど権限がないとのこと
UWPアプリではあらかじめ使う機能を有効にしないといけません。そしてそれはUnityエディターではPlayer Settings->Publishing Settings->Capabilitiesで設定できます。

f:id:knasa:20170707031551p:plain

 今回はネットワーク通信の受信をするのでInternetClientServerにチェックを入れます。
ちなみにInternetClientでは送信のみのようです(HoloToolkitから設定できるのはこっち)。

しかし、これでも同じエラーが出ます。もう涙目です。
じゃあどうするかというとUnityのビルドで生成された.slnで”Package.appxmanifest”を編集します。

f:id:knasa:20170707032400p:plain

Package.appmanifestを開いて機能から「インターネット(クライアントとサーバー)」にチェックを入れます。本来Unityでのチェックが反映されているはずだと思うんですが……

f:id:knasa:20170707033601p:plain

これでHoloLensでUDPの受信ができるようになりました。ふぃー。
UDPClientUWP.csって名前にしちゃったけどClientじゃなくてServerだった……

そして送信側、こちらはUnity関係ないUWPアプリです。

gist.github.com

画面にはテキストボックス(InputText)とボタンがあります。テキストボックスの中身をボタンを押したときに送信するようになっています。
もちろんこれもUWPアプリなので「インターネット(クライアント)」を有効にしないといけないわけですが、なんと勝手に有効になっています。どうやら必要なコードだと判断して有効にしてくれていたようです。VS優秀か。
正直こちらに関してはエラーで詰まるなどなく動いてくれました。助かった。

と、長々と書きましたが、こんな感じでHoloLensとUWPアプリのUDP通信ができるようになりました。UnityとHoloToolkitの組み合わせは便利なんですけど、まだバグが多いのか再起動すると消えるエラーとか、エラーでてるのにビルドできるし動くしみたいな現象が再現性なく多発するのでめげそうになります。
なによりUnityとUWPで同じように書けないのが面倒、Unityの機能から外れると急に崖になってる感じです。
とにもかくにもUDP通信ができたので、やりたいことが進められます。

 

参考記事(ほんと助かりました)