yotiky Tech Blog

とあるエンジニアの備忘録

Unityを取り巻くアーキテクチャ 第1部 「MVxとLayered Circle」

最近Unityをゆるく触ってる感じで、"やりたいことをやれるやり方で"実装すると「こりゃ死ぬな..」と思ったので、界隈の設計方針調べてるところです。

アーキテクチャは読み手の解釈に委ねられる部分が多かったり、提唱されたあとも進化や変化があったりするので、あくまで現時点でそれぞれどう捉えてるかの覚書と考察を。雑ならくがき、雑がき。

※編集したり更新したりする予定です。

目次

概要

つらつらと書き始めたら思いの外風呂敷が広がってしまったので、「MVxとLayerd Circleについて」、「DDDについて」、「Unityで実装する話」の3部構成くらいに収まるといいなぁと言った所です。
今回の記事は第一部「MVxとLayerd Circleについて」にあたります。

一応自分のアーキテクチャ絡みそうな経験を軽く記す。 大体C#使って開発してて歴はそこそこ長め、古くはクラサバや3層アーキテクチャWPFでMVVMのまさかり飛んでる頃にはWPFのプロジェクト携わったり、ゲームのサーバーサイドをASP.NET MVCでやったりなどなどしてました。

アーキテクチャ

アーキテクチャは、アプリケーションをどう動かすか、どう設計するかのパターン。
アーキテクチャは、性質上読み手の解釈が異なることも多く、定義自体の”解釈の議論”が発生してとても不毛だとは思う。
より明確であったなら、使えるか使えないか、どう使うかの判断だけで済むのだが、プロジェクトの状況によってコンテキストも違うので全部ケースバイなんて無理だし難しいよねと。テクノロジーや時間経過によっても変化や進化はあるし。

ただアーキテクチャは経験則によるパターンなので、「何に対してどう対処したのか」を自分なりに理解し、使える武器として揃えておくことは有用だ思う。使える時に使えばいいし、合わなければ使わなければよい。

名前をつけて提唱された"アーキテクチャ"は、アプリケーションに骨子を与える。登場する箱は主なキーパーソンでしかない。それ以外に定義しちゃダメってわけでもないし、箱すら分離して崩したっていい。そもそも着眼点以外がふわっと定義されてたりもするし、プロジェクトに合わせて柔軟に対応すればいい。
最終的には我々がやってることは学問じゃないので、アーキテクチャが正解かどうかではなく、目の前の問題に対処できたかどうかの方が大事だ。
ひとつ注意するとすれば、アーキテクチャの目的、意味は理解しておきたい。アーキテクチャの目的を理解していないと、名のある"アーキテクチャ"が"アーキテクチャ"として意味をなさなくなるし、箱の名前と役割も変わってくる。

「MVx」と「Layered Circle」

「MVx」は、Viewとそれ以外をどうつなぎ合わせるかのアーキテクチャ
"それ以外"ってのが肝で、"x"にあたる"つなぎ方"以外は全部Modelとし表現してる。この解釈を間違えると"x"にビジネスロジックが入り込んでまさかりが飛んでくる。

「Layered Circle(Hexagonal/Onion/Clean Architecture)」は、ドメイン(ビジネスルール)とそれ以外をどう分離するかのアーキテクチャ
Hexagonal / Onion / CA は細部(表現)は違えど目的は同じ。
如何にドメイン(ビジネスルール)を外的要因から隔離し、ドメイン(ビジネスルール)をCleanに保つか、これが肝。

これらは視点が異なる。 だから、同列に並べてどちらかを取捨選択するものでもない。組み合わせられるものは組み合わせればいいし、コンセプトの違いで組み合わせられないものはそもそも選べない。

MVx

MVC」、「MVP」、「MVVM」などが存在するが、詳細は各々調べて自分なりの解釈を探ってもらうとして、雑に筆者の解釈を記すと、

「C」は入力を受けて「M」に処理を依頼、「V」を選択して出力する。「C」が入力を受けるためにフレームワークを使ってルーティングすることが多い。「V」から直接入力されるわけではない。

f:id:yotiky:20180926043432p:plain

「P」は「V」のイベントをハンドリングして「M」に処理を依頼、その結果を「V」に反映する仲介役。「P」が主体となり「V」と「M」を調整する。(PassiveとかPushとかいう方)

f:id:yotiky:20180926043441p:plain

VM」は「V」に最適化されたデータオブジェクト。「V」と表裏一体にくっついてて、「P」のようにイベントをハンドリング、または「V」から叩かれたりして「M」を呼ぶ。「V」は「VM」と、「VM」は「M」とバインディングすることで、「M」の値の変更通知を「VM」が受け自身に反映する。また「VM」の変更通知は「V」へ伝播し「V」が更新される。

f:id:yotiky:20180926043448p:plain


凡例
f:id:yotiky:20180928024130p:plain

  1. 関連。矢印の先端を参照することを意味する。矢印の先端に依存する。
  2. 関連に対する戻り値。矢印の先端に対して値が戻される。
  3. 事前にバインディングすることで、イベント通知または値の変更通知が矢印の先端に対して発行される。双方向の場合、値の変更通知が双方向の場合と、イベント通知と値の変更通知が混合されてる場合も含む。
  4. 関連に対する「実質の呼び出し」として使用した。

MVVMの関連について

MVVMを極めし人々は、View→ViweModel、ViewModel→Modelにおいてはvoidのメソッドを叩き、変更通知が伝播することでViewに結果が投影されるという。 1
WikipediaによるとMVVMの提唱者はMSのJohn Gossmanらしく、2005年のBlog 2ではデザイナーとの作業の分離に着目して書かれてて、要はViewとそれ以外を分離してどう紐付けるかの話をしている。分業に夢を抱いて大きく舵を切ってた時代。
一方で国内WPF界隈で発展したMVVMに関する知見は、個人的には哲学的に昇華したという捉え方で、実務においてはそこに囚われすぎ無くても良いと思っている。具体的には、ViewModel→Modelにおいては、ケースバイケースで戻り値を持つメソッドを叩いてもいいのでは、と考える。

f:id:yotiky:20181031024402p:plain

ViewModel→Modelにおいてvoidのメソッドを叩くのが引っかかるのは、変更通知の伝播が最低2層、Model内で伝播が発生すると3層以上になってしまう点。
手に乗るサイズのコード量であれば気にしすぎなケースもあれど、多人数での作業だったりコードに歴史が重ねられると何が何に関連しているか把握しづらくなってしまう。
ViewModel層で介在(フィルタ)したり、伝播の粒度(束ねたり)なんかも気にしたくなるケースがあったりなかったり。水の波紋のように中心に触れると綺麗に広がってくのは気持ちが良いとは思うけど。

Layered Circle

参考にさせていただいたサイトによると、Hexagonal Architectureが2005年(PoEAA的には2002年?)、Onion Architectureが2008年、Clean Architectureが2013年に提唱されたようだ。

Hexagonal Architecture

PoEAAでパターンとして提唱されたものらしい。
目的は、自動化された回帰テスト
本質は、「内部(アプリケーション)」を「外部」から切り離すこと。
主なキーワードは、アプリケーション、ポート、アダプター、外部デバイス
テストを外部デバイスGUIやDB)に依存せず、ドライバー/モックを使ってアプリケーション(ビジネスロジック)だけを繰り返しテストさせるためのアーキテクチャ、というかパターン。
サンプルはあるもののそういう風にしようぜってだけで、具体的にアーキテクチャとしてどう組もうまではなさそう、回帰テスト目的なのでそこまでってことか。 ポートは差込口で、アダプターはそのポートに差し替え可能な外部デバイスとの繋ぎ部分。例えばDBアクセスのロジックとそれに差し替わるMock(これは外部デバイスないので自身で完結)は、一つのポートにぶら下がるアダプターとなる。
ポートは6個あるわけではなく、複数あるよってことでHexagonの形。

f:id:yotiky:20180926043543p:plain

他のアーキテクチャの影響を受けて、解釈は大きく、進化してそうな気配はある。


凡例
f:id:yotiky:20180928024318p:plain

  1. インターフェイス
  2. 実現。インターフェイスを実装することを意味する。

Onion Architecture

提唱者はMicrosoft MVPっぽい。Microsoft のテクノロジがベースとなったアーキテクチャのようだ。
目的は、あまり安定しない(変化しやすい)コードから影響を受けないようにすること。
主なキーワードは、外周のUser Interface, Infrastructure, Testsと、
Application Core と呼ばれる内側3層がApplication Services, Object Services, Object Model。

Infrastructureを外部化しアダプターコードを間に置くことで疎結合にする事は、Hexagonal Architectureと同じとなる。ただ、ドメインをCleanに保つこと自体を目的とはしておらず、副次的にそうなると言った感じか。事実DDDの有無にはかかわらず機能するとなっている。

原典によると、小規模なWebサイトには適していないし、複雑なアプリケーションや寿命の長いビジネスアプリケーションに適しているとなっている。これはBehavior Contracts(動作の取り決め)のためにInterfaceの使用を強要し、依存関係逆転によりInfrastructureの外部化を強制するため。

OnionにおけるInfrastructureはData層に当たると思われるが、レイヤードアーキテクチャの図ではUIからも参照されてて謎めいているが、Utility Servicesを含みそうな書き方なのでその矢印だろうか、、Part3においてUIからInfrastructureへの矢印は消えているのだが、、、罪深い。

f:id:yotiky:20180926043550p:plain

Onion Architectureの特徴の一つは、他のアーキテクチャではレイヤーは隣接するレイヤーに結合するのに対し、Onion Architectureは内側であればレイヤーを跨いで結合することができる点にある。
変化しやすいコード、User InterfaceおよびInfrastructureの実装部分は外周におき、内部のビジネスルールはInterfaceを使った関連を築き、処理を実装する。
必須ではないものの、IoC(Inversion of Control:制御の反転)コンテナ、DIコンテナ等を使うことを強くお勧めしている。

f:id:yotiky:20180926043557p:plain

Clean Architecture

Hexagonal、Onion、その他いくつかのアーキテクチャを受けて焼き直したアーキテクチャ
目的は、フレームワーク、UI、DB、外部機能からビジネスルールを独立し、さらにそれだけでテスト可能とすること。
表現が違うだけで本質は同じ。ビジネスルールを外的要因から分離する。
主なキーワードは、
Frameworks&Drivers : UI, Web, DB, Devices, External Interfaces
Interface Adapters : Controllers, Presenters, Gateways
Application Business Rules : Use Cases
Enterprise Business Rules : Entities

ビジネスルールはフレームワーク、UI、DBから独立しており、そのためUIはウェブからコンソールへビジネスルールの変更なしに置き換えられる。 一番外側は外的なモジュールやツール、DB、UIだとUIで使われるフレームワークやライブラリ、その他諸々の業務の関心ごと以外となる外的要因。

f:id:yotiky:20180926043608p:plain

個人的解釈のポイント。

EntityはEnterprise Business Rules層に属しており、ビジネスルールをカプセル化するので所謂POCOではない。ドメイン、ビジネスルールと呼ばれる部分。システム化することに依存しないビジネスルール。

Use CaseはApplication Business Rules層で、上記ビジネスルールをシステム化することで必要となる繋ぎ、Facade的な役割を持つ。EntityはUse Caseの影響を受けないとなるので、真ん中にもやはりInterfaceが必要なのかもしれない。

Interface Adapters層ではアプリケーション内部のビジネスルールに適したデータ形式と、外部で利用するのに適したデータ形式とを変換する。また外側のFrameworks&Drivers層とApplication Business Rules層の処理の橋渡し役となる。

原典によると、「MVC」は、Mは単なるデータ構造とし、VCはInterface Adapter層ってことで説明されてる。Controllerは入力を受けて処理を依頼し、UseCaseでEntityを経由(ビジネスルール)したのち、Presenterが出力を仲介する。(なぜかPが登場...)

Frameworks&Drivers層は、DBやWebフレームワークとなっている。DBそのものはアプリケーションの境界外であるはずなので外に追い出して、そことの繋ぎ(Driverやそのラッパーあたり)を持ってきた。それは詳細を知っていて詳細をすべて内包する形で影響を閉じ込める。

境界をまたがるいたるところで、依存関係逆転の原則、すなわちInterfaceと実装による疎結合が使われるとあるのでこのような実装になると思われる。
境界を流れるデータについても、外側の円において、内側の円にとって使いやすい形にすることになるだろう。(データを使い回さず各層で詰め替えるならば)Interfaceが内側の円にあるので自然とそうなるはず。

参考にさせて頂いたサイト

CEDEC2018 セッション資料・レポート一覧

見つけたセッション資料やレポートのリンク集です。 公式で公開されるまでは、折を見て更新していく予定。 これもあるよってのあれば教えて頂けると幸いです。

※公式で資料公開されてるので以降更新されません。CEDiLを参照ください。
また動画の一部はCEDECチャンネルYoutube版で見れるようです。

資料

レポート

各サイト一覧ページ

DAY 1

  • 基調講演
  • 明快で軽快! Nintendo SwitchのUI

  • オンラインゲームのこれまでとこれから

    • 「オンラインゲームのこれまでとこれから」を国内主要オンラインゲームのスタッフが語る【CEDEC 2018】Gamer
    • オンラインゲームの過去と未来を大討論! ロングセッションをガッツリお届け!! 【CEDEC 2018】ファミ通.com
  • VIVE

  • 女神転生 UIデザイン制作方法

    • CEDEC 2018】アイトラッカーユーザーテストがキーとなる『D×2 真・女神転生リベレーション』での新しいUIデザイン制作方法の試みと発見 Social Game Info
  • トキメキとは何か

    • 乙女に愛されるキャラクターはどう作る? 乙女向け目覚ましアプリ『MakeS-おはよう、私のセイ-』ディレクターが語る制作術【CEDEC 2018】 ファミ通.com
    • CEDEC 2018]「女性が伴侶を選ぶポイント」を分析し,魅力的なキャラクターを生み出す。「トキメキとは何か ~乙女を恋へと導く新たなアプローチ~」レポート 4Gamer.net
    • 乙女を恋に導くための仕掛け―「MakeS -おはよう、私のセイ-」セッションレポート!【CEDEC 2018】Gamer
  • ハシラスVR

    • CEDEC 2018]「大規模VRはオンラインゲームに近い」ハシラスが目指す最先端VRの先にあるもの GamesIndustry
  • FFXIVエス

    • CEDEC 2018】「FFXIV」はなぜ500個単位のクエストを実装できるのか? GAME Watch
    • FFXIV」のクエストはこのように作られていた! 秘蔵資料も飛び出したセッションをレポート【CEDEC 2018】Gamer
  • esports

  • Vtuberのビジネス

    • CEDEC 2018]バーチャルYouTuberの課題は罰ゲーム? 同時運用の苦労などが語られた講演「Vtuberのビジネスの最新動向と必要とされる技術について」をレポート 4Gamer.net
    • CEDEC 2018 Vtuber事業で必要な技術や機材とは? CyberVがめざす次代のVtuber表現 SPARKが選んだVtuber関連機材 IGN
  • オートプレイによる最適なパラメータシミュレーション

    • CEDEC 2018】『ダンまち~メモリア・フレーゼ~』運用チームが導入するオートプレイによる最適なパラメータシミュレーションの枠組みとは? Social Game Info
  • ゼノブレイド2のレイマーチング

  • SpriteStudio

    • 汎用2Dアニメーション作成ツール「SpriteStudio」最新バージョンの新機能とは【CEDEC 2018】インサイド
  • ハリウッド映画音楽

  • 弱いロボット

    • CEDEC 2018]ロボットと人間の関係性に注目した「弱いロボット」の可能性 4Gamer.net

DAY 2

DAY 3

HoloLens(実機)でリモートデバッグする

HoloLensの実機でアプリをデバッグするにはどうしているでしょうか。

これまでは何となくVisual Studioデバッグを開始(F5)を実行していましたが、毎回アプリのビルド、配置から始まり、コードを変更していないにもかかわらずアプリの起動まで時間を要する作業でした。 加えてHoloLensが眠ってて配置に失敗したり、なぜかアプリの起動で必ず一度コケるなどあるあるですかね?

そんなわけで重い腰を上げてプロセスにアタッチできないか調べてみました。

目次

TL;DR

HoloLens(実機)でアプリをリモートデバッグする手順を紹介します。

開発環境

  • Unity:2017.4.5f1
  • MRTK:2017.4.1
  • VisualStudio:2017
  • OS:HoloLens RS4

手順

  1. Unityが出力したソリューションファイルを開きます。
  2. Visual Studioのメニューで、[デバッグ > その他デバッグターゲット > インストールされているアプリケーションパッケージのデバッグ }を実行します。
  3. image.png (59.0 kB)

USB経由で接続したい場合

  1. USBでHoloLensを接続している場合は、接続の種類で「デバイス」を選択します。
  2. インストールされているアプリ パッケージで、アプリを起動していない場合は実行されていないの中から、アプリを起動している場合は実行中の中から、対象のアプリを選択してアタッチをクリック。

    image.png (59.3 kB)

  3. 成功すればいつもの画面になります。

    image.png (86.4 kB)

Wifi経由で接続したい場合

  1. Wifiの場合はペアリングが必要になります。接続の種類で「リモートコンピューター」を選択して、「変更」をクリック。
  2. リモート接続ウィンドウで、手動で構成にアドレスを入力し、ユニバーサル(暗号化されていないプロトコル)を選択して、「選択」をクリック。

    screenshot.266.png (13.1 kB)

  3. ペアリングがまだの場合ペアリングを求められます。 HoloLens側は Settings > Update & Security > For developers > Device discovery にある「Pair」をクリックするとcode が表示されるので、Visual Studio に入力してペアリングしてください。

  4. インストールされているアプリ パッケージで、アプリを起動していない場合は実行されていないの中から、アプリを起動している場合は実行中の中から、対象のアプリを選択してアタッチをクリック。

    image.png (58.2 kB)

  5. こちらも成功すればデバッグ状態になります。

    image.png (79.5 kB)

HoloLensでVuforiaを使う ~応用編~ (Unity&MRTK 2017世代)

前回、Vuforiaを導入する基本的な手順をまとめました。今回は応用編として、基本から少しだけ踏み出したTipsを紹介しておきます。
前回の続きになりますのでご覧になられていにいない方は以下を参照ください。

yotiky.hatenablog.com

また、Vuforiaに関してはこちらにもまとまってますのでぜひご一読ください。 github.com

目次

TL;DR

Vuforiaは位置合わせでよく使いますが、Vuforia自体が重かったり、(RS4の場合)画像キャプチャや動画撮影などが行えないなどの不都合が生じるため、不要になったタイミングで機能をOFFにします。しかし、このまま機能をOFFにするとImageTarget配下にあるコンテンツ自体が表示されなくなってしまうため、コンテンツ自体は外に逃した上で、ImageTargetのPositionとRotaitonを同期するようにしなければなりません。また、ImageTarget配下に何もないとトラッキングができているのかどうかわからなくなってしまうので、代わりの3Dオブジェクトをおいてあげます。

f:id:yotiky:20180816032331p:plain

サンプルで使用したソースコードは下記を参照ください。

github.com

内容

白い皿

まず、コンテンツ自体をVuforiaの有効/無効に関係なく表示するため外に逃がします。
新たにModelsという空のGameObjectを作成し、ImageTarget配下にあった3Dオブジェクトをドラッグアンドドロップします。
ModelsのTransformが初期位置になっているか確認した上で行ってください。子に含めた後に親の位置やサイズを変えると、子の値も相対的に変化してしまいます。

image.png (2.7 kB)

さてこのままでは、Vuforiaがトラッキングできているのかどうかわからなくなってしまうため、代わりの3Dオブジェクトを置きます。 よく使っているのは、マーカーと同じサイズの薄い皿(板)を少しだけ浮かせて表示させる方法です。

ImageTarget配下にマーカーと同じサイズの薄い皿を作成します。

image.png (2.4 kB) image.png (7.4 kB)

image.png (82.6 kB)

青い皿

HoloLensでUnityを触り始めた人がすぐ直面するのが、3Dオブジェクトに色を付けたいだけなのにDefault-Materialが何一つ変更できなくて途方にくれることではないでしょうか。 最初の一歩として白以外の色を使ってみましょう。

Project上で新たにMaterialを作成します。

image.png (3.9 kB)

Rendering ModeをTransparentにし、Albedoで適当な色を選択します。

image.png (56.3 kB)

前項で作った薄い皿のInspectorを開いて、Materialsを展開し、作ったばかりのMaterialをドラッグ・アンド・ドロップします。

image.png (10.6 kB)

image.png (92.1 kB)

これでVuforiaがマーカーを認識すると、青い皿がオーバラップされて表示されるようになりました。 Unity のレンダリングには マテリアル、シェーダー、テクスチャ が使用されますが、ここではこれ以上踏み込まないので各自調べてみてください。

皿はマーカーと同じサイズを指定しているので現実のマーカーにピタッと重なって欲しいところですが、実際は多少ズレます。これはVuforiaを使った位置合わせで全体のズレを意味します。ただ、HoloLensは現状ではこの手法が一番現実的な実装で誤差の少ない手法になるかと思いますので、そのへんも頭の片隅においておくと良いかもしれません。

VuforiaをOFFにする

次にVufoiraがマーカーを認識したらコンテンツの位置を同期します。 今回は同期のトリガーとして青い皿をタップすることにします。

Project上で、MarkerTrackerと言う名前のスクリプトを追加します。
ほかのオブジェクトにマーカーの位置を通知する方法は、ReactiveProperty、Event(delegete)、直接受け渡しするなどなど色々ありますが、ここでは簡略化してActionを使います。
ソースコードは以下の通りです。

public class MarkerTracker : MonoBehaviour, IInputClickHandler
{
    public Action<Transform> Click { get; set; }

    public void OnInputClicked(InputClickedEventData eventData)
    {
        if(Click != null)
        {
            Click(transform);
        }
    }
}

このクラスはアタッチしたGameObjectをクリック(AirTap)すると、プロパティのCilckアクションに自分のTransformを渡して呼ぶだけのクラスです。 利用したい側でCilckアクションに処理を紐づけてあげます。

続いて、PositionAdjustmentと言う名前のスクリプトを追加します。 こちらは利用したい側になります。

public class PositionAdjustment : MonoBehaviour
{
    public MarkerTracker marker;
    public GameObject contents;

    void Start()
    {
        marker.Click = m =>
        {
            contents.transform.position = m.position;
            contents.transform.rotation = m.rotation;
            contents.SetActive(true);
            VuforiaBehaviour.Instance.enabled = false;
        };

        contents.SetActive(false);
    }
}

UnityのInspectorでMrakerTrackerと位置合わせしたいコンテンツ(3Dオブジェクト)を設定し、それぞれをひもづけて処理します。
起動時にコンテンツは非表示にし、クリックした際に位置を合わせて表示します。 また位置合わせが完了するので、このタイミングでVuforiaをOFFにします。

ハマることがあるとすると、GameObjectやVuforiaを無効化した際にアタッチされてるコードが無効化されて上手く機能しないケースでしょうか。 GameObjectの関係やコードの寄生先には注意をはらいましょう。

最後にUnity上でスクリプトをアタッチしましょう。

青い皿にMarkerTrackerを。

image.png (2.3 kB) image.png (12.8 kB)

ModelsにPositionAdjustmentを。

image.png (2.5 kB) image.png (22.0 kB)

PositionAdjutsment > Markerには青い皿、Contnetsにはコンテンツ(3Dオブジェクト)を設定します。

image.png (96.4 kB)

以上になります。
実機で動作を確認してみてください。

HoloLensでVuforiaを使う (Unity&MRTK 2017世代)

サンプルやデモ用のアプリを作るに当たり、Unityプロジェクトを作成し、Vuforiaの設定まで終わらせる一連の流れがよくでてきます。参考にさせて頂いているサイトはいくつかありますが、情報が古くなって所々違いが見られるため、手順の覚書として書き記しておきます。(主に私用)

Vuforiaに関してはこちらにもまとまってますのでぜひご一読ください。 github.com

目次

TL;DR

Vuforiaのポータルでマーカー画像を登録します。
そのデータをもとにHoloLensでマーカーを認識し、マーカーの上に3Dオブジェクトを表示します。

サンプルで使用したソースコードは下記を参照ください。

github.com

開発環境

  • Unity:2017.4.5f1
  • MRTK:2017.4.1
  • VisualStudio:2017
  • OS:HoloLens RS4

内容

マーカーの準備

適当な画像を用意してください。
もしくは、QRコード生成サイトなどでQRコードの画像をマーカーとして入手しましょう。

image.png (22.2 kB)

上記はサイト「QRのススメ」さんで作成した例です。 小さいとHoloLensが認識しづらいのでなるべく大きなサイズで作ります。 また、VuforiaのターゲットにPNGが使えないためJPGで保存します。

VuforiaポータルでDatabaseを取得

ライセンスの発行

Vuforiaのポータルサイトに行ってログインします。 アカウントを作っていない人は作りましょう。

ログインしたら、Develop > License Manager > Get Development Keyをクリック。
ライセンスについては各自調べてください。開発用には無料のDevelopmentで大丈夫(なはず)。

image.png (20.5 kB)

App NameをつけてチェックボックスにチェックしてConfirmをクリック。

image.png (42.8 kB)

作成したアプリケーションのページを開いてライセンスキーをコピーしておきましょう。あとでUnityで使います。

screenshot.206.png (14.2 kB)

Databaseの作成と取得

Develop > Target Manager > Add Databaseをクリック。

image.png (18.8 kB)

名前をつけて、Deviceを選択してCreateをクリック。

image.png (21.9 kB)

作成したデータベースを開いて、Add Targetをクリック。

Single Imageを選んで、用意した画像またはQRコードを選択します。 WidthはUnity上でも変更できるので1(単位はm)、NameをつけてAddをクリック。

image.png (53.0 kB)

これでターゲットに登録されます。
Ratingは特徴点で、星が多いと画像が認識されやすくなります。 対象のターゲットを開いて、画像下のShow Featuresを押すと特徴点を確認できます。

image.png (36.4 kB)

Databaseに含めるマーカーを選択してDownload Database、もしくはDownload Database(All)をクリックでもOK。
Unity Editorを選んでDownloadをクリック。

image.png (26.6 kB)

[Database名].unitypackage が保存されます。後ほどUnityにインポートします。

プロジェクトの初期設定

Unity を起動して、新しいプロジェクトを作成します。
まずはMRTKのunitypackageをインポート。

続いてメニューから、Mixed Reality Toolkit > Configure の項目を上から順に実行します。

  • Apply Mixed Reality Project Settings > そのままApplyをクリック。

    上記Applyで変更される箇所を補足しておくとつぎの通りです。 撮り忘れましたがQuality SettingsもHoloLens用にVery Lowで設定されているかと思います。

    Build Settings

    変更前 変更後
    -PlatformをUWPに変更
    -Target DeviceをHoloLensに変更

    Player Settings

    変更前 変更後
    -Scripitng Backendを.NETに変更
    -Virtual Reality Supported をHoloLens用に設定

    Tag & Layers

    変更前 変更後
    -Layer31にSpatial Mappingを設定
  • Apply Mixed Reality Sceen Settngis > そのままApplyをクリック。

    開いているシーンをHoloLens用にカスタマイズされるので、Ctrl + S でシーンに名前をつけて保存します。

    image.png (15.8 kB)

    ついでに Ctrl + Shift + B でBuild Settingsを開き、忘れがちなビルドにシーンの追加をしておきましょう!

  • Apply UWP Capability Settings > 以下のように設定してApplyをクリック。

    これでPlayer Settings > Publishing Settings > Capabilities に設定が反映されます。

    image.png (18.4 kB)

ここまでがHoloLensの実装を始める前の一般的なプロジェクトの準備でした。 使いたい機能に応じて設定の内容は適宜変更してください。

実装

続いて、Vuforiaの機能を使ったアプリのコンテンツを実装していきます。
予めダウンロードしておいたVuforiaのDatabaseをインポート。

image.png (56.1 kB)

Player Settings > XR Settings を開いて、Vuforia Augmented Reality Supported にチェック。

image.png (11.5 kB)

HierarchyにVuforia > Image を追加します。
Vuforiaのアセットをインポートするか聞かれるので、Importをクリック。

image.png (39.1 kB)

Assets > Resources > VuforiaConfiguration を開いて次のように設定します。

  • 予めコピーしておいたライセンスキーを入力します。

    image.png (10.4 kB)

  • Digital Eyewear と Databaseを設定します。

    image.png (17.9 kB)

    Databaseを設定した後にVuforiaのImageオブジェクトを追加するとDatabaseが更新されるので注意してください。
    また、Vuforiaの設定周りをいじくってるときにも、たまにDatabaseの設定が初期化されてることがあるので要注意です。

先程追加したImageオブジェクトの設定に戻ります。
Inspectorを開いて、DatabaseとImage Targetをインポートした画像のものに変更します。
Advancedの項目を開いて、実際にHoloLensのCameraで取り込む際のマーカーの実寸サイズを入力します。(単位はmなので10cmなら0.1など)

image.png (22.5 kB)

Hierarchy上で、Imageオブジェクトの配下に任意の3Dオブジェクトを追加します。配下に追加することで、VuforiaがImageを捉えた時だけマーカーの上に表示されるようになります。 サンプルでは豆腐をマーカーの少し上に浮かせています。

image.png (6.9 kB)

MixedRealityCameraにVuforiaBehaviourコンポーネントを追加します。

image.png (5.9 kB)image.png (28.5 kB)

また、その上にあるMixed Reality Camera ManagerのTransparent Display Setitngs > Near Clip は、3Dモデルが表示される一番短い距離です。 デフォルトの0.85(m)が推奨ではありますが、デスクで作業していると0.85がとても遠いので任意で近くまで表示しましょう。(もちろん非推奨)

ここまででVuforiaに登録したマーカーを使って、マーカーを認識するとその上にオブジェクトが表示されるようになりました。

ビルドして実行

Build Settingsを開き、Unity C# Projectsにチェックを入れてBuildをクリック。
UWPフォルダを作成し、そのフォルダを選択して実行します。Appフォルダを指定するサンプルもありますが、後述のMRTKのBuild WindowのデフォルトはUWPなので、揃えておけば余計なフォルダが増えなくてよいかと思います。
ビルドが成功するとエクスプローラでUWPフォルダが開きますので、Visual Studioでソリューションを開きます。

または、Mixed Reality Toolkit > Build Windowをクリックし、ウィンドウを表示します。
Unity Build Optionsタブで、Unity C# Projectsにチェックを入れてBuild Unity Projectをクリック。
ビルドが成功するとダイアログで教えてくれるので、Open in Visual Studioをクリックすれば直接ソリューションを開けます。

ソリューションを開いたら、プラットフォームをx86にし、実行環境をDeviceに変更して実行します。

以上。

注意事項

執筆時の開発環境であるRS4では、VuforiaをONにしているとCameraを専有するらしく、写真、動画の撮影ができません。 Vuforiaは位置合わせに使われることが多く、不要になったら機能をOFFにすることをおすすめします。

動作の確認は取れていませんが、以下の挙動をするとの情報があります。
バージョンによって挙動が異なるので、VuforiaでCameraを使う場合はそのあたり気にして調べてみてください。

  • RS1:録画のみいける
  • RS4:全部ダメ
  • RS5:録画もPreviewもいけるらしい?

※詳細分かれば更新かけます。ご存知の方ご一報を。

esaのチートシート

編集履歴

  • 2018/11/16 注釈の項を追加
  • 2018/11/22 タイトルに#と/を含める書き方を追加

公式よりMarkdown記法

Markdown以外

Markdown Tips

  • ページ内リンク
  • 改行
    • 行末に半角スペース2つ
    • <br/>
  • 画像(サイズ指定)
    • <img src="URL" width="数値" alt="代替テキスト">
  • Tableの配置
左揃え 中央揃え 右揃え
aaa bbb ccc

  1. hogehogehogehoge

  2. fugafugafugafuga

  3. piyopiyopiyopiyo

  4. hauhau

Visual Studio で Azure Functions に HttpTrigger のAPIを作成する

TL;DR

Visual Studio でAzure Functions のAPIを実装します。その後、Visual StudioからAzure App Serviceを新規作成し発行します。 また、PostmanおよびPowershellを使ってローカルでの確認とAzureで動作確認します。 APIはHttpTrigger(GET/POST)で、リクエストとレスポンスにJSONを使います。 開発環境の準備は含まれないため、Visual Studio を使用する Azure Functions の開発 などを参考にしてください。

目次

プロジェクトを作成する

  1. Visual Studioで[ファイル > 新規作成 > プロジェクト]を選択し、[Visual C# > Cloud > Azure Functions]を選択して、任意の場所に設定してOKをクリック。 f:id:yotiky:20180809002055p:plain
  2. Http Trigger を選択してOKをクリック。 f:id:yotiky:20180809002059p:plain
  3. Function1という名前のサンプルが生成される。

Functionを実装する

  1. クラス名とファイル名、FunctionNameを「Echo」に変更。
    public static class Echo
    {
        // Invoke-RestMethod -Uri "http://localhost:7071/api/Echo" -Method Post -ContentType "application/json" -Body '{"message":"Hello Azure Functions" }'
        // Invoke-RestMethod -Uri "https://YourFunctionURL" -Method Post -ContentType "application/json" -Body '{"message":"Hello Azure Functions" }'  
        [FunctionName("Echo")]
        public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log)
        {
  1. リクエストクラスを作成。
class EchoRequest
{
    public string message { get; set; }
}
  1. 変数名をnameからmsgに。
  2. クエリパラメータを取得するところをnameからmessageに修正。
  3. bodyからパラメータを取得するところを修正。
            if (msg == null)
            {
                // Get request body
                var data = await req.Content.ReadAsAsync<EchoRequest>();
                msg = data?.message;
            }
  1. Jsonを扱う名前空間を追加。
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
  1. レスポンスを作成する部分を実装する。
    1. IdとしてGuidのハイフンなしを発行。
        var jObject = new JObject();
        jObject["Id"] = Guid.NewGuid().ToString("N");
        jObject["Message"] = msg;

        var res = req.CreateResponse(HttpStatusCode.OK);
        res.Content = new StringContent(jObject.ToString(Formatting.None));

        return res;

ローカルで実行する

  1. F5でデバッグ実行。
  2. Postman で試す方法。
    1. GET
      1. GETを選択、URL欄右のParamsをクリックで展開してパラメータ入力 f:id:yotiky:20180809002102p:plain
    2. POST
      1. POSTを選択、BodyタブでrawとJSON(application/json)を選んでJSONで入力(GETのパラメータが残ってたらチェック外す) f:id:yotiky:20180809002105p:plain
  3. PowerShellで試す方法。
Invoke-RestMethod -Uri "http://localhost:7071/api/Echo" -Method Post -ContentType "application/json" -Body '{"message":"Hello Azure Functions" }'

Azureに発行する

  1. プロジェクト右クリックから発行を押すか、ビルド > [プロジェクト名] を発行する を選択する
  2. 今回は新規作成
    f:id:yotiky:20180809002109p:plain
  3. 必要な情報を入力または選択して作成
    f:id:yotiky:20180809002112p:plain

Azure Functionsの動作確認

  1. Azure Portal で関数のURLを取得する
    f:id:yotiky:20180809002116p:plain f:id:yotiky:20180809002120p:plain
  2. PostmanまたはPowerShellで実行。ローカルで実行するを参照。