HoloLens (第 1 世代) と Azure 308: クロスデバイス通知
Note
Mixed Reality Academy のチュートリアルは、HoloLens (第 1 世代) と Mixed Reality イマーシブ ヘッドセットを念頭に置いて編成されています。 そのため、それらのデバイスの開発に関するガイダンスを引き続き探している開発者のために、これらのチュートリアルをそのまま残しておくことが重要だと考えています。 これらのチュートリアルが、HoloLens 2 に使用されている最新のツールセットや操作に更新されることは "ありません"。 これらは、サポートされているデバイス上で継続して動作するように、保守されます。 今後、HoloLens 2 の開発方法を説明する新しいチュートリアルが公開される予定です。 この通知は、それらのチュートリアルが投稿されたときにリンクと共に更新されます。
このコースでは、Azure Notification Hubs、Azure テーブル、Azure Functions を使用して、Notification Hubs 機能を Mixed Reality アプリケーションに追加する方法について説明します。
Azure Notification Hubs は、開発者が、パーソナル設定されたターゲット プッシュ通知をあらゆるプラットフォームに送信できるようにする Microsoft のサービスであり、すべてクラウド内で実現できます。 これにより、開発者はシナリオに応じて、エンド ユーザーとの通信、および各種アプリケーション間の通信も効率的に行うことができます。 詳細については、 Azure Notification Hubs page を参照してください。
Azure Functions は、開発者が小さなコードである "関数" を Azure で実行できるようにする Microsoft のサービスです。 これにより、ローカル アプリケーションではなく、クラウドに作業を委任することができ、多くの利点を得られます。 Azure Functions は、C#、F#、Node.js、Java、PHP など、いくつかの開発言語をサポートしています。 詳細については、 Azure Functions page を参照してください。
Azure テーブルは、開発者が構造化された非 SQL データをクラウドに格納し、どこからでも簡単にアクセスできるようにする Microsoft のクラウド サービスです。 このサービスには優れたスキーマレス設計が提供されており、必要に応じてテーブルを進化させることができるため、高い柔軟性が得られます。 詳細については、「 Azure Tables page」を参照してください。
このコースを修了すると、次のことができる Mixed Reality イマーシブ ヘッドセット アプリケーションと、デスクトップ PC アプリケーションを手に入れることができます。
デスクトップ PC アプリを使用すると、ユーザーはマウスを使用して、2D 空間 (X および Y) 内でオブジェクトを動かせます。
PC アプリ内のオブジェクトの動きは、JSON を使用してクラウドに送信されます。これは、オブジェクトの ID、型、変換情報 (X および Y 座標) を含む文字列の形式になります。
デスクトップ アプリと同一のシーンを持つ Mixed Reality アプリは、Notification Hubs サービス (デスクトップ PC アプリによって更新されたばかりの) から、オブジェクトの動きに関する通知を受け取ります。
オブジェクトの ID、型、変換情報が含まれる通知を受け取ると、Mixed Reality アプリは、受信した情報を独自のシーンに適用します。
お客様のアプリケーションで、結果をどのようにデザインと統合するかは、お客様次第です。 このコースは、Azure のサービスを Unity プロジェクトに統合する方法を学べることを目的としています。 このコースで得られた知識を使用して、ご自分の Mixed Reality アプリケーションを強化しましょう。 このコースは自己完結型のチュートリアルであり、他の Mixed Reality ラボとは直接の関連はありません。
デバイス サポート
コース | HoloLens | イマーシブ ヘッドセット |
---|---|---|
MR と Azure 308: クロスデバイス通知 | ✔️ | ✔️ |
Note
このコースは主に Windows Mixed Reality イマーシブ(VR)ヘッドセットに焦点を当てていますが、このコースで学んだことを Microsoft HoloLens にも応用できます。 このコースに取り組む過程で、HoloLens をサポートするために採用する必要のある変更に関するノートが表示されます。 HoloLens を使用すると、音声キャプチャ中に反響音が生じることがあります。
前提条件
Note
このチュートリアルは、Unity と C# の基本的な使用経験がある開発者を対象としています。 また、このドキュメント内の前提条件や文章による説明は、執筆時 (2018 年 5 月) にテストおよび検証された内容であることをご了承ください。 「ツールのインストール」の記事に記載されているように、最新のソフトウェアを自由に使用できます。ただし、このコースの情報は、以下に記載されているものよりも新しいソフトウェアで見つかったものと完全に一致するとは限りません。
このコースでは、次のハードウェアとソフトウェアをお勧めします。
- イマーシブ (VR) ヘッドセットの開発に必要な Windows Mixed Reality と互換性のある開発用 PC
- 開発者モードが有効になっている Windows 10 Fall Creators Update (またはそれ以降)
- 最新の Windows 10 SDK
- Unity 2017.4
- Visual Studio 2017
- 開発者モードが有効になっている Windows Mixed Reality イマーシブ (VR) ヘッドセットまたは Microsoft HoloLens
- Azure のセットアップと、Notification Hubs へのアクセスのためのインターネット アクセス
開始する前に
- このプロジェクトをビルドする際の問題を避けるために、このチュートリアルで紹介するプロジェクトをルートまたはルートに近いフォルダーに作成することを強くお勧めします (フォルダー パスが長いと、ビルド時に問題が発生する可能性があります)。
- Microsoft デベロッパー ポータルとアプリケーション登録ポータルの所有者である必要があります。そうでない場合、第 2 章でアプリにアクセスするためのアクセス許可が付与さません。
章 1 章 - Microsoft デベロッパー ポータルでアプリケーションを作成する
Azure Notification Hubs サービスを使用するには、アプリケーションで通知を送受信できるようにアプリケーションを登録する必要があるため、Microsoft デベロッパー ポータルでアプリケーションを作成する必要があります。
Microsoft デベロッパー ポータルにログインします。
Microsoft アカウントにログインする必要があります。
ダッシュボードで、[新しいアプリの作成] をクリックします。
ポップアップが表示されます。ここで、新しいアプリの名前を予約する必要があります。 テキスト ボックスに適切な名前を入力します。選択した名前が使用可能な場合は、テキスト ボックスの右側にチェック マークが表示されます。 使用可能な名前が挿入されたら、ポップアップの左下にある [製品名の予約] ボタンをクリックします。
これでアプリが作成されたので、次の章に進むことができます。
章 2 章 - 新しいアプリの資格情報を取得する
アプリケーション登録ポータルにログインすると、新しいアプリが一覧表示されます。ここで、Azure portal 内で Notification Hubs サービスをセットアップするために使用する資格情報を取得します。
アプリケーション登録ポータルに移動します。
警告
ログインするには、Microsoft アカウントを使用する必要があります。
これは、前の章の Windows ストア デベロッパー ポータルで使用した Microsoft アカウントである必要があります。アプリは [マイ アプリケーション] セクションに表示されます。 見つかったアプリをクリックすると、アプリ名と [登録] が表示された新しいページに移動します。
登録ページを下にスクロールして、[アプリケーション シークレット] セクションとアプリの [パッケージ SID] を見つけます。 次の章の Azure Notification Hubs サービスの設定で使用するために両方をコピーします。
章 3 章 - Azure portal のセットアップ: Notification Hubs サービスを作成する
アプリの資格情報を取得したら、Azure portal に移動する必要があります。ここでは、Azure Notification Hubs サービスを作成します。
Azure Portal にログインします。
Note
まだ Azure アカウントをお持ちでない方は、作成する必要があります。 このチュートリアルを教室やラボで受講している場合は、インストラクターや監督者に新しいアカウントの設定方法を質問してください。
ログインしたら、左上隅にある[新規作成] をクリックして、[Notification Hub] を検索し、Enter キーを押します。
Note
新しいポータルでは、[新規作成] という文字列が [リソースの作成] に置き換えられることがあります。
新しいページに、Notification Hubs サービスの説明が表示されます。 このプロンプトの左下にある [作成] ボタンを選択すると、このサービスとの関連付けが作成されます。
[作成] をクリックしたら、次のようにします。
このサービス インスタンスに必要な名前を入力します。
このアプリに関連付けることができる名前空間を指定します。
[場所] を選択します。
[リソース グループ] を選択するか、新規に作成します。 リソース グループは、Azure アセットのコレクションの監視、アクセス制御、プロビジョニング、課金管理を行う方法を提供します。 1 つのプロジェクト (例: これらのラボなど) に関連するすべての Azure サービスを共通のリソース グループの下に保持することをお勧めします。
Azure リソース グループについては、リソース グループの管理方法のリンクから詳細をご覧ください。
適切な [サブスクリプション] を選択します。
またお客様は、本サービスに適用されるご契約条件を理解していることを確認する必要があります。
[作成] を選択します
[作成] をクリックしたら、サービスが作成されるのを待つ必要があります。これには 1 分ほどかかることがあります。
サービス インスタンスが作成されると、ポータルに通知が表示されます。
通知の[リソースに移動]ボタンをクリックして、新しいサービスインスタンスを探します。 新しい Notification Hub サービス インスタンスが表示されます。
ページの中央にある [概要] ページで、[Windows (WNS)] をクリックします。右側のパネルが変更され、以前に設定したアプリのパッケージ SID とセキュリティ キーを必要とする 2 つのテキスト フィールドが表示されるようになります。
詳細を正しいフィールドにコピーしたら、[保存] をクリックします。Notification Hub が正常に更新されると通知を受け取ります。
第 4 章 - Azure portal のセットアップ: テーブル サービスを作成する
Notification Hubs サービス インスタンスを作成したら、Azure portal に戻ります。ここでは、ストレージ リソースを作成して Azure テーブル サービスを作成します。
まだサインインしていない場合は、Azure portal にログインします。
ログインしたら、左上隅にある[新規作成] をクリックして、ストレージ アカウントを検索し、Enter キーをクリックします。
Note
新しいポータルでは、[新規作成] という文字列が [リソースの作成] に置き換えられることがあります。
一覧から [ストレージ アカウント - BLOB、ファイル、テーブル、キュー] を選択します。
新しいページに、ストレージ アカウント サービスの説明が表示されます。 このプロンプトの左下にある [作成] ボタンを選択すると、このサービスのインスタンスが作成されます。
[作成] をクリックすると、パネルが表示されます。
このサービス インスタンスに必要な [名前] を入力します (すべて小文字である必要があります)。
[デプロイ モデル] で、[リソース マネージャー] を選択します。
[アカウントの種類] ドロップダウン メニューで [ストレージ (汎用 v1)] を選択します。
適切な [場所] を選択します。
[レプリケーション] ドロップダウン メニューで、[読み取りアクセス geo 冗長ストレージ (RA-GRS)] を選択します。
[パフォーマンス] で [標準] をクリックします。
[安全な転送が必須] セクションで [無効] を選択します。
[サブスクリプション] ドロップダウン メニューから、適切なサブスクリプションを選択します。
[リソース グループ] を選択するか、新規に作成します。 リソース グループは、Azure アセットのコレクションの監視、アクセス制御、プロビジョニング、課金管理を行う方法を提供します。 1 つのプロジェクト (例: これらのラボなど) に関連するすべての Azure サービスを共通のリソース グループの下に保持することをお勧めします。
Azure リソース グループについては、リソース グループの管理方法のリンクから詳細をご覧ください。
このオプションを選択する場合は、[仮想ネットワーク] を [無効] のままにします。
Create をクリックしてください。
[作成] をクリックしたら、サービスが作成されるのを待つ必要があります。これには 1 分ほどかかることがあります。
サービス インスタンスが作成されると、ポータルに通知が表示されます。 通知をクリックして、新しいサービス インスタンスを確認します。
通知の[リソースに移動]ボタンをクリックして、新しいサービスインスタンスを探します。 新しいストレージ サービス インスタンスの概要ページが表示されます。
[概要] ページで、右側にある [テーブル] をクリックします。
右側のパネルが変更されて、テーブル サービスの情報が表示されます。ここで、新しいテーブルを追加する必要があります。 これを行うには、左上隅にある + Table ボタンをクリックします。
新しいページが表示されます。ここには、テーブル名を入力する必要があります。 これは、後の章でアプリケーション内のデータを参照するために使用する名前です。 適切な名前を挿入し、[OK] をクリックします。
新しいテーブルが作成されると、テーブル サービスのページ (下部) にそれが表示されるようになります。
第 5 章 - Visual Studio で Azure テーブルを完成させる
Table サービスのストレージ アカウントがセットアップされたので、それにデータを追加します。これは、情報の格納と取得に使用されます。 テーブルの編集は Visual Studio を使用して行うことができます。
Visual Studio を開きます。
メニューから [表示]>[Cloud Explorer] をクリックします。
Cloud Explorer がドッキングされたアイテムとして開きます (読み込みに時間がかかる場合があります)。
Note
"ストレージ アカウント" の作成に使用したサブスクリプションが表示されない場合は、次のことを確認してください。
Azure portal で使用したものと同じアカウントにログインしている。
[アカウント管理] ページからサブスクリプションを選択しました (アカウントの設定からフィルターを適用する必要がある場合があります)。
Azure クラウド サービスが表示されます。 アカウントを展開するには、ストレージ アカウントを見つけて、その左側の矢印をクリックします。
展開が完了すると、新しく作成されたストレージ アカウントが使用できるようになっているはずです。 そのストレージの左側にある矢印をクリックし、それが展開されたら、[テーブル] を見つけて、その横にある矢印をクリックし、前の章で作成したテーブルを表示します。 テーブル名をダブルクリックします。
テーブルが Visual Studio ウィンドウの中央に開きます。 + (プラス) の付いたテーブル アイコンをクリックします。
エンティティの追加を求めるウィンドウが表示されます。 合計 3 つのエンティティを作成し、それぞれに複数のプロパティを指定します。 PartitionKey と RowKey が既に指定されていることがわかります。これらは、データを検索するためにテーブルで使用されるためです。
PartitionKey と RowKey について値を次のように更新します (追加する行プロパティごとにこの操作を行ってください。ただし、RowKey は毎回インクリメントします)。
[プロパティの追加] をクリックして、データの行を追加します。 最初の空のテーブルを次のテーブルのようにします。
完了したら、OK をクリックします。
警告
[X]、[Y]、[Z] の各エントリの [型] を [Double] に変更したことを確認します。
テーブルにデータ行があることがわかります。 + (プラス) アイコンをもう一度クリックして、別のエンティティを追加します。
追加のプロパティを作成し、次に示すように新しいエンティティの値を設定します。
別のエンティティを追加するには、最後の手順を繰り返します。 このエンティティの値を次に示すように設定します。
これで、テーブルは以下のようになります。
これでこの章が完了しました。 必ず保存してください。
第 6 章 - Azure Function App を作成する
Azure Function App を作成します。これは、デスクトップ アプリケーションによって呼び出され、テーブル サービスを更新し、Notification Hub を介して通知を送信します。
まず、必要なライブラリを Azure Function で読み込むことができるファイルを作成する必要があります。
メモ帳を開きます (Windows キーを押して「notepad」と入力します)。
メモ帳を開いた状態で、下の JSON 構造を挿入します。 その作業が完了したら、それをデスクトップに project.json として保存します。 名前付けが正しいことが重要です。.txt のファイル拡張子が付いていないことを確認してください。 このファイルでは、関数が使用するライブラリを定義します。NuGet を使用していた場合は、なじみのある内容です。
{ "frameworks": { "net46":{ "dependencies": { "WindowsAzure.Storage": "7.0.0", "Microsoft.Azure.NotificationHubs" : "1.0.9", "Microsoft.Azure.WebJobs.Extensions.NotificationHubs" :"1.1.0" } } } }
Azure Portal にログインします。
ログインしたら、左上隅の [新規作成] をクリックして、Function App を検索して Enter キーを押します。
Note
新しいポータルでは、[新規作成] という文字列が [リソースの作成] に置き換えられることがあります。
新しいページには、Function App サービスの説明が表示されます。 このプロンプトの左下にある [作成] ボタンを選択すると、このサービスとの関連付けが作成されます。
[作成] をクリックしたら、次のように入力します。
[アプリ名] に、このサービス インスタンスに必要な名前を入力します。
サブスクリプションを選択します。
適切な価格レベルを選択します。これが初めて作成する Function App サービスの場合は、無料レベルを使用できるはずです。
[リソース グループ] を選択するか、新規に作成します。 リソース グループは、Azure アセットのコレクションの監視、アクセス制御、プロビジョニング、課金管理を行う方法を提供します。 1 つのプロジェクト (例: これらのラボなど) に関連するすべての Azure サービスを共通のリソース グループの下に保持することをお勧めします。
Azure リソース グループについては、リソース グループの管理方法のリンクから詳細をご覧ください。
[OS] では、目的のプラットフォームである [Windows] をクリックします。
[ホスティング プラン] を選択します (このチュートリアルでは、従量課金プランを使用しています)。
Location を選択します (前の手順で作成したストレージと同じ場所を選択します)
[ストレージ] セクションで、前の手順で作成したストレージ サービスを選択する必要があります。
このアプリで Application Insights は必要ないため、[オフ] のままにしておいてもかまいません。
Create をクリックしてください。
[作成] をクリックしたら、サービスが作成されるのを待つ必要があります。これには 1 分ほどかかります。
サービス インスタンスが作成されると、ポータルに通知が表示されます。
通知をクリックして、新しいサービス インスタンスを確認します。
通知の[リソースに移動]ボタンをクリックして、新しいサービスインスタンスを探します。
[関数] の横にある + (プラス記号) アイコンをクリックして、新規作成します。
中央のパネル内に関数の作成ウィンドウが表示されます。 パネルの上半分にある情報を無視し、[Custom function] (カスタム関数) をクリックします。これは、下部 (下に示すように、青い領域内) の近くにあります。
ウィンドウ内の新しいページには、さまざまな関数の種類が表示されます。 下にスクロールして紫色の種類を表示し、[HTTP PUT] 要素をクリックします。
重要
ページの下までスクロールする必要がある場合がありますが (Azure portal の更新が行われている場合、この図はまったく同じように見えない可能性があります)、HTTP PUT という要素を探しています。
[HTTP PUT] ウィンドウが表示されます。ここで、関数を構成する必要があります (下の図を参照してください)。
[言語] のドロップダウン メニューを使用して [C#] を選択します。
[名前] に適切な名前を入力します。
[認証レベル] ドロップダウン メニューで、[関数] を選択します。
[テーブル名] セクションでは、以前にテーブル サービスの作成に使用したのと同じ名前を使用する必要があります (同じ大文字小文字を含む)。
[ストレージ アカウント接続] セクションで、ドロップダウン メニューを使用して、そこからストレージ アカウントを選択します。 表示されていない場合は、セクション タイトルの隣にある [新規] のハイパーリンクをクリックして、ストレージ アカウントが表示される別のパネルを表示します。
[作成] をクリックすると、設定が正常に更新されたことを示す通知を受け取ります。
[作成] をクリックすると、関数エディターにリダイレクトされます。
関数エディターに次のコードを挿入します (関数内のコードを置き換えます)。
#r "Microsoft.WindowsAzure.Storage" using System; using Microsoft.WindowsAzure.Storage; using Microsoft.WindowsAzure.Storage.Table; using Microsoft.Azure.NotificationHubs; using Newtonsoft.Json; public static async Task Run(UnityGameObject gameObj, CloudTable table, IAsyncCollector<Notification> notification, TraceWriter log) { //RowKey of the table object to be changed string rowKey = gameObj.RowKey; //Retrieve the table object by its RowKey TableOperation operation = TableOperation.Retrieve<UnityGameObject>("UnityPartitionKey", rowKey); TableResult result = table.Execute(operation); //Create a UnityGameObject so to set its parameters UnityGameObject existingGameObj = (UnityGameObject)result.Result; existingGameObj.RowKey = rowKey; existingGameObj.X = gameObj.X; existingGameObj.Y = gameObj.Y; existingGameObj.Z = gameObj.Z; //Replace the table appropriate table Entity with the value of the UnityGameObject operation = TableOperation.Replace(existingGameObj); table.Execute(operation); log.Verbose($"Updated object position"); //Serialize the UnityGameObject string wnsNotificationPayload = JsonConvert.SerializeObject(existingGameObj); log.Info($"{wnsNotificationPayload}"); var headers = new Dictionary<string, string>(); headers["X-WNS-Type"] = @"wns/raw"; //Send the raw notification to subscribed devices await notification.AddAsync(new WindowsNotification(wnsNotificationPayload, headers)); log.Verbose($"Sent notification"); } // This UnityGameObject represent a Table Entity public class UnityGameObject : TableEntity { public string Type { get; set; } public double X { get; set; } public double Y { get; set; } public double Z { get; set; } public string RowKey { get; set; } }
Note
関数は、含まれているライブラリを使用して、Unity シーン内で移動されたオブジェクトの名前と場所を受け取ります (UnityGameObjectと呼ばれる C# オブジェクトとして)。 このオブジェクトは、作成されたテーブル内のオブジェクト パラメーターを更新するために使用されます。 次に、この関数は、作成された Notification Hub サービスを呼び出します。これにより、すべての登録済みアプリケーションが通知されます。
コードを配置したら、[保存] をクリックします。
次に、ページの右側にある < (矢印) アイコンをクリックします。
パネルが右側からスライドします。 そのパネルで [アップロード] をクリックすると、ファイル ブラウザーが表示されます。
以前にメモ帳で作成した project.json ファイルに移動してクリックし、[開く] ボタンをクリックします。 このファイルは、関数が使用するライブラリを定義します。
ファイルがアップロードされると、右側のパネルに表示されます。 これをクリックすると、関数エディター内で開かれます。 これは、次の図 (下の手順 23) とまったく同じになるはずです。
次に、左側のパネルの [関数] の下にある [統合] リンクをクリックします。
次のページの右上隅にある [詳細エディター] (次の手順を参照) をクリックします。
function.json ファイルが中央のパネルで開きます。これは、次のコード スニペットで置き換える必要があります。 これにより、ビルドする関数と、関数に渡されるパラメーターが定義されます。
{ "bindings": [ { "authLevel": "function", "type": "httpTrigger", "methods": [ "get", "post" ], "name": "gameObj", "direction": "in" }, { "type": "table", "name": "table", "tableName": "SceneObjectsTable", "connection": "mrnothubstorage_STORAGE", "direction": "in" }, { "type": "notificationHub", "direction": "out", "name": "notification", "hubName": "MR_NotHub_ServiceInstance", "connection": "MRNotHubNS_DefaultFullSharedAccessSignature_NH", "platform": "wns" } ] }
エディターは次の図のようになります。
挿入した入力パラメーターがテーブルとストレージの詳細と一致しないため、情報を更新する必要があることがわかります。 次の手順で対処するため、ここではこの操作を行わないでください。 ここでは、ページの右上隅にある標準のエディターのリンクをクリックするだけにして、戻ります。
標準エディターに戻り、[入力] の下にある [Azure Table Storage (テーブル)] をクリックします。
次の内容が自分の情報と一致しない場合があるため、一致していることを確認します (次の手順の下に画像があります)。
テーブル名: Azure Storage、Tables サービス内で作成したテーブルの名前。
ストレージ アカウント接続:ドロップダウン メニューと共に表示される [新規] をクリックすると、ウィンドウの右側にパネルが表示されます。
関数アプリをホストするために以前に作成したストレージ アカウントを選択します。
ストレージ アカウントの接続値が作成されていることがわかります。
完了したら、必ず [保存] を押します。
[入力] ページが次のようになり、自分の情報が表示されます。
次に、[出力] の下の [Azure Notification Hub (通知)] をクリックします。 次の内容が自分の情報と一致しない場合があるため、一致していることを確認します (次の手順の下に画像があります)。
Notification Hub 名: これは、前に作成した Notification Hub サービス インスタンスの名前です。
Notification Hubs の名前空間接続: ドロップダウン メニューの横に表示される [新規] をクリックします。
[接続] ポップアップが表示されます (下図を参照)。ここでは、以前に設定した Notification Hub の名前空間を選択する必要があります。
中央のドロップダウン メニューから Notification Hub 名を選択します。
[ポリシー] ドロップダウン メニューを DefaultFullSharedAccessSignature に設定します。
[選択] ボタンをクリックして戻ります。
これで [出力] ページは以下のようになりますが、自分の情報が代わりに使用されています。 必ず [保存] を押します。
警告
Notification Hub 名を直接編集しないでください (これは、前の手順に正しく従っていれば、詳細エディターを使用して行う必要があります)。
この時点で、関数が動作していることを確認するために、その関数をテストする必要があります。 手順は次のとおりです。
関数のページにもう一度移動します。
関数のページに戻り、ページの右端にある [テスト] タブをクリックして、[テスト] ブレードを開きます。
ブレードの [要求本文] テキストボックスに、次のコードを貼り付けます。
{ "Type":null, "X":3, "Y":0, "Z":1, "PartitionKey":null, "RowKey":"Obj2", "Timestamp":"0001-01-01T00:00:00+00:00", "ETag":null }
テスト コードを配置した状態で、右下にある [実行] ボタンをクリックすると、テストが実行されます。 テストの出力ログは、関数コードの下のコンソール領域に表示されます。
警告
上記のテストが失敗した場合は、上記の手順に厳密に従っていること、特に統合パネル内の設定を再確認する必要があります。
第 7 章 - デスクトップ Unity プロジェクトを設定する
重要
現在作成中のデスクトップ アプリケーションは、Unity エディターでは動作しません。 アプリケーションのビルド後に、Visual Studio (またはデプロイされたアプリケーション) を使用して、エディターの外部で実行する必要があります。
次に示すのは、Unity と Mixed Reality で開発するための一般的な設定であり、他のプロジェクトのテンプレートとしても適しています。
Mixed Reality イマーシブ ヘッドセットをセットアップしてテストします。
Note
このコースでは、モーションコントローラーを必要としません。 イマーシブ ヘッドセットの設定についてサポートが必要な場合は、Windows Mixed Reality の設定方法のリンクに従います。
Unity を開き、[新規] をクリックします。
Unity プロジェクト名を指定する必要があります。「UnityDesktopNotifHub」と入力します。 プロジェクトの種類が [3D] に設定されていることを確認します。 [場所] を適切な場所に設定します (ルート ディレクトリに近い方が適しています)。 [Create project]\(プロジェクトの作成\) をクリックします。
Unity を開いた状態で、既定のスクリプト エディターが Visual Studio に設定されているかどうか確認することをお勧めします。 お気に入り編集>に移り、新しいウィンドウから外部ツールにナビゲートします。 [外部スクリプト エディター] を [Visual Studio 2017] に変更します。 [環境設定] ウィンドウを閉じます。
次に、[File] (ファイル)>[Build Settings] (ビルド設定) に移動して、[Universal Windows Platform] (ユニバーサル Windows プラットフォーム) を選択します。次に、[Switch Platform] (プラットフォームの切り替え) ボタンをクリックして選択を適用します。
[File]\(ファイル\)>[Build Settings]\(ビルド設定\) で、次のことを確認します。
[Target Device] (ターゲット デバイス) が [Any Device] (任意のデバイス) に設定されている
このアプリケーションはデスクトップ用であるため、[Any Device] (任意のデバイス) にする必要があります
[Build Type] (ビルドの種類) が [D3D] に設定されている
[SDK] が [最新のインストール] に設定されている。
[Visual Studio Version] (Visual Studio のバージョン) が [Latest installed] (最新のインストール) に設定されている
[Build and Run] (ビルドと実行) が [Local Machine] (ローカル マシン) に設定されている
ここで、シーンを保存し、ビルドに追加することをお勧めします。
これを行うには、[Add Open Scenes] (開いているシーンを追加) を選択します。 保存ウィンドウが表示されます。
これと、今後のシーン用の新しいフォルダーを作成し、[新しいフォルダー] ボタンを選択して、新しいフォルダーを作成し、「Scenes」という名前を付けます。
新しく作成した Scenes フォルダーを開き、[File name:]\(ファイル名\) テキスト フィールドに「NH_Desktop_Scene」と入力して [Save]\(保存\) をクリックします。
[ビルド設定] の残りの設定は、ここでは既定値のままにしておきます。
同じウィンドウで、[Player Settings] (プレーヤー設定) ボタンをクリックすると、[Inspector] (インスペクター) が配置されているスペースに関連パネルが開かれます。
このパネルでは、いくつかの設定を確認する必要があります。
[Other Settings] (その他の設定) タブで、次の内容を確認します。
[Scripting Runtime Version] (スクリプト ランタイムのバージョン) が [Experimental (.NET 4.6 Equivalent)] (試験段階 (.NET 4.6 と同等)) になっている
[スクリプト バックエンド] が [.NET] である。
[API Compatibility Level]\(API 互換性レベル\) が [.NET 4.6] である。
[Publishing Settings]\(公開設定\) タブ内の [Capabilities]\(機能\) で、次の内容を確認します。
InternetClient
Build 設定 Unity C# プロジェクトはグレー表示されなくなりました。この横にあるチェックボックスをオンにします。
[ビルド設定] ウィンドウを閉じます。
シーンとプロジェクトを保存します ([File] (ファイル)>[Save Scene / File] (シーン/ファイルの保存)>[Save Project] (プロジェクトの保存))。
重要
このプロジェクト (デスクトップ アプリ)で "Unity のセットアップ" コンポーネントをスキップして、そのままコードに進みたい場合は、この .unitypackage をダウンロードして、カスタム パッケージとしてプロジェクトにインポートしてから、第 9 章から続けてください。 その場合でも、スクリプト コンポーネントを追加する必要があります。
章 8 章 - Unity で DLL をインポートする
Azure Storage for Unity を使用します (これ自体が .Net SDK for Azure を利用します)。 詳細については、Azure Storage for Unity に関するこのリンクを参照してください。
現在、Unity には、インポート後にプラグインを再構成する必要がある既知の問題があります。 バグが解決された後は、これらの手順 (このセクションの 4 - 7) は不要になります。
SDK を独自のプロジェクトにインポートするには、GitHub から最新の .unitypackage がダウンロードされていることを確認してください。 次に、以下を実行します。
[Assets] (資産) > [Import Package] (パッケージのインポート) > [Custom Package] (カスタム パッケージ) メニュー オプションを使用して、.unitypackage を Unity に追加します。
ポップアップ表示される [Import Unity Package] (Unity パッケージのインポート) ボックスで、[Plugin] (プラグイン)>[Storage] (ストレージ) の下にあるすべてを選択できます。 このコースでは不要なため、その他のすべてをオフにします。
[Import]\(インポート\) ボタンをクリックして、各項目をプロジェクトに追加します。
[Project] (プロジェクト) ビューの [Plugins] (プラグイン) の下の Storage フォルダーに移動して、以下のプラグイン "のみ"を選択します。
- Microsoft.Data.Edm
- Microsoft.Data.OData
- Microsoft.WindowsAzure.Storage
- Newtonsoft.Json
- System.Spatial
これらのプラグイン選択した状態でuncheck Any Platform と uncheck WSAPlayer Apply をクリックします。
Note
Unity エディターで使用するためにのみこれらの特定のプラグインをマークしています。 これは、プロジェクトが Unity からエクスポートされた後に使用される、同じプラグインの異なるバージョンが WSA フォルダー内にあるためです。
Storage プラグイン フォルダーで、以下のみを選択します。
Microsoft.Data.Services.Client
[Platform Settings] (プラットフォームの設定) の下の [Don't Process] (処理しない) ボックスをオンにして、[Apply] (適用) をクリックします。
Note
Unity アセンブリ パッチャはこのプラグインを処理するのが困難であるため、このプラグインを [Don't Process] (処理しない) としてマークしています。 処理されていなくてもこのプラグインは動作します。
第 9 章 - デスクトップ Unity プロジェクトで TableToScene クラスを作成する
ここで、このアプリケーションを実行するコードを含むスクリプトを作成する必要があります。
作成する必要のある最初のスクリプトは TableToScene です。これは次の役割を担います。
- Azure テーブル内のエンティティを読み取ります。
- テーブル データを使用して、生成するオブジェクトとその位置を決定します。
作成する必要がある 2 番目のスクリプトは CloudScene です。これは次の役割を担います。
- 左クリック イベントを登録して、ユーザーがシーン内でオブジェクトをドラッグできるようにします。
- この Unity シーンからオブジェクト データをシリアル化し、それを Azure Function App に送信します。
このクラスを作成するには、次の手順を実行します。
[Project] (プロジェクト) パネルにある Asset フォルダーを右クリックし、[Create] (作成)>[Folder] (フォルダー) の順にクリックします。 フォルダーに「Scripts」という名前を付けます。
先ほど作成したフォルダーをダブルクリックして開きます。
Scripts フォルダー内で右クリックし、[作成]>[C# スクリプト] をクリックします。 スクリプトに TableToScene という名前を付けます。
スクリプトをダブルクリックして、それを Visual Studio 2017 で開きます。
次の名前空間を追加します。
using Microsoft.WindowsAzure.Storage; using Microsoft.WindowsAzure.Storage.Auth; using Microsoft.WindowsAzure.Storage.Table; using UnityEngine;
クラス内に次の変数を挿入します。
/// <summary> /// allows this class to behave like a singleton /// </summary> public static TableToScene instance; /// <summary> /// Insert here you Azure Storage name /// </summary> private string accountName = " -- Insert your Azure Storage name -- "; /// <summary> /// Insert here you Azure Storage key /// </summary> private string accountKey = " -- Insert your Azure Storage key -- ";
Note
Azure portal で、accountName 値を Azure Storage サービス名に置き換え、accountKey 値を Azure Storage サービスのキー値に置き換えます (次の図を参照)。
ここで、クラスを初期化するための Start () および Awake() の各メソッドを追加します。
/// <summary> /// Triggers before initialization /// </summary> void Awake() { // static instance of this class instance = this; } /// <summary> /// Use this for initialization /// </summary> void Start() { // Call method to populate the scene with new objects as // pecified in the Azure Table PopulateSceneFromTableAsync(); }
TableToScene クラス内で、Azure テーブルから値を取得し、それを使用してシーン内の適切なプリミティブを生成するメソッドを追加します。
/// <summary> /// Populate the scene with new objects as specified in the Azure Table /// </summary> private async void PopulateSceneFromTableAsync() { // Obtain credentials for the Azure Storage StorageCredentials creds = new StorageCredentials(accountName, accountKey); // Storage account CloudStorageAccount account = new CloudStorageAccount(creds, useHttps: true); // Storage client CloudTableClient client = account.CreateCloudTableClient(); // Table reference CloudTable table = client.GetTableReference("SceneObjectsTable"); TableContinuationToken token = null; // Query the table for every existing Entity do { // Queries the whole table by breaking it into segments // (would happen only if the table had huge number of Entities) TableQuerySegment<AzureTableEntity> queryResult = await table.ExecuteQuerySegmentedAsync(new TableQuery<AzureTableEntity>(), token); foreach (AzureTableEntity entity in queryResult.Results) { GameObject newSceneGameObject = null; Color newColor; // check for the Entity Type and spawn in the scene the appropriate Primitive switch (entity.Type) { case "Cube": // Create a Cube in the scene newSceneGameObject = GameObject.CreatePrimitive(PrimitiveType.Cube); newColor = Color.blue; break; case "Sphere": // Create a Sphere in the scene newSceneGameObject = GameObject.CreatePrimitive(PrimitiveType.Sphere); newColor = Color.red; break; case "Cylinder": // Create a Cylinder in the scene newSceneGameObject = GameObject.CreatePrimitive(PrimitiveType.Cylinder); newColor = Color.yellow; break; default: newColor = Color.white; break; } newSceneGameObject.name = entity.RowKey; newSceneGameObject.GetComponent<MeshRenderer>().material = new Material(Shader.Find("Diffuse")) { color = newColor }; //check for the Entity X,Y,Z and move the Primitive at those coordinates newSceneGameObject.transform.position = new Vector3((float)entity.X, (float)entity.Y, (float)entity.Z); } // if the token is null, it means there are no more segments left to query token = queryResult.ContinuationToken; } while (token != null); }
TableToScene クラスの外部では、テーブル エンティティをシリアル化および逆シリアル化するためにアプリケーションによって使用されるクラスを定義する必要があります。
/// <summary> /// This objects is used to serialize and deserialize the Azure Table Entity /// </summary> [System.Serializable] public class AzureTableEntity : TableEntity { public AzureTableEntity(string partitionKey, string rowKey) : base(partitionKey, rowKey) { } public AzureTableEntity() { } public string Type { get; set; } public double X { get; set; } public double Y { get; set; } public double Z { get; set; } }
Unity エディターに戻る前に、必ず保存してください。
[Hierarchy] (階層) パネルから [Main Camera] (メイン カメラ) をクリックして、そのプロパティが [Inspector] (インスペクター) に表示されるようにします。
Scripts フォルダーを開いた状態で、スクリプト TableToScene ファイルを選択し、Main Camera にドラッグします。 結果は次のようになります。
第 10 章 - デスクトップ Unity プロジェクトで CloudScene クラスを作成する
作成する必要がある 2 番目のスクリプトは CloudScene です。これは次の役割を担います。
左クリック イベントを登録して、ユーザーがシーン内でオブジェクトをドラッグできるようにします。
この Unity シーンからオブジェクト データをシリアル化し、それを Azure Function App に送信します。
2 番目のスクリプトを作成するには、次のようにします。
Scripts フォルダー内で右クリックし、[Create] (作成)、[C# Script] (C# スクリプト) をクリックします。 スクリプトの名前を CloudScene にします。
次の名前空間を追加します。
using Newtonsoft.Json; using System.Collections; using System.Text; using System.Threading.Tasks; using UnityEngine; using UnityEngine.Networking;
次の変数を挿入します。
/// <summary> /// Allows this class to behave like a singleton /// </summary> public static CloudScene instance; /// <summary> /// Insert here you Azure Function Url /// </summary> private string azureFunctionEndpoint = "--Insert here you Azure Function Endpoint--"; /// <summary> /// Flag for object being moved /// </summary> private bool gameObjHasMoved; /// <summary> /// Transform of the object being dragged by the mouse /// </summary> private Transform gameObjHeld; /// <summary> /// Class hosted in the TableToScene script /// </summary> private AzureTableEntity azureTableEntity;
次の図に示すように、Azure portal で、azureFunctionEndpoint の値を Azure 関数アプリ サービスにある Azure 関数アプリの URL に置き換えます。
ここで、クラスを初期化するための Start () および Awake() の各メソッドを追加します。
/// <summary> /// Triggers before initialization /// </summary> void Awake() { // static instance of this class instance = this; } /// <summary> /// Use this for initialization /// </summary> void Start() { // initialise an AzureTableEntity azureTableEntity = new AzureTableEntity(); }
Update() メソッド内に、マウス入力とドラッグを検出する以下のコードを追加します。これにより、シーン内の GameObjects が移動されます。 ユーザーがオブジェクトをドラッグ アンド ドロップした場合、オブジェクトの名前と座標がメソッド UpdateCloudScene() に渡されて、Azure Function App サービスが呼び出されます。これにより、Azure テーブルが更新され、通知がトリガーされます。
/// <summary> /// Update is called once per frame /// </summary> void Update() { //Enable Drag if button is held down if (Input.GetMouseButton(0)) { // Get the mouse position Vector3 mousePosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 10); Vector3 objPos = Camera.main.ScreenToWorldPoint(mousePosition); Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; // Raycast from the current mouse position to the object overlapped by the mouse if (Physics.Raycast(ray, out hit)) { // update the position of the object "hit" by the mouse hit.transform.position = objPos; gameObjHasMoved = true; gameObjHeld = hit.transform; } } // check if the left button mouse is released while holding an object if (Input.GetMouseButtonUp(0) && gameObjHasMoved) { gameObjHasMoved = false; // Call the Azure Function that will update the appropriate Entity in the Azure Table // and send a Notification to all subscribed Apps Debug.Log("Calling Azure Function"); StartCoroutine(UpdateCloudScene(gameObjHeld.name, gameObjHeld.position.x, gameObjHeld.position.y, gameObjHeld.position.z)); } }
次に、以下のように UpdateCloudScene() メソッドを追加します。
private IEnumerator UpdateCloudScene(string objName, double xPos, double yPos, double zPos) { WWWForm form = new WWWForm(); // set the properties of the AzureTableEntity azureTableEntity.RowKey = objName; azureTableEntity.X = xPos; azureTableEntity.Y = yPos; azureTableEntity.Z = zPos; // Serialize the AzureTableEntity object to be sent to Azure string jsonObject = JsonConvert.SerializeObject(azureTableEntity); using (UnityWebRequest www = UnityWebRequest.Post(azureFunctionEndpoint, jsonObject)) { byte[] jsonToSend = new System.Text.UTF8Encoding().GetBytes(jsonObject); www.uploadHandler = new UploadHandlerRaw(jsonToSend); www.uploadHandler.contentType = "application/json"; www.downloadHandler = new DownloadHandlerBuffer(); www.SetRequestHeader("Content-Type", "application/json"); yield return www.SendWebRequest(); string response = www.responseCode.ToString(); } }
コードを保存して Unity に戻ります。
CloudScene スクリプトを Main Camera にドラッグします。
[Hierarchy] (階層) パネルから [Main Camera] (メイン カメラ) をクリックして、そのプロパティが [Inspector] (インスペクター) に表示されるようにします。
Scripts フォルダーを開いた状態で、CloudScene スクリプトを選択し、Main Camera にドラッグします。 結果は次のようになります。
第 11 章 - デスクトップ プロジェクトを UWP にビルドする
このプロジェクトの Unity セクションに必要なすべての手順が完了しました。
[Build Settings] (ビルド設定) に移動します ([File] (ファイル)>[Build Settings] (ビルド設定))。
[ビルド設定] ウィンドウで、[ビルド] をクリックします。
[エクスプローラー] ウィンドウがポップアップ表示され、ビルドの場所を入力するように求められます。 新しいフォルダーを作成し (左上隅の [New Folder]\(新規フォルダー\) をクリックします)、それに BUILDS という名前を付けます。
新しい BUILDS フォルダーを開き、フォルダーをもう 1 つ作成し ([新しいフォルダー] をもう一度使用します)、NH_Desktop_App という名前を付けます。
NH_Desktop_App を選択します。 [フォルダーの選択] をクリックします。 プロジェクトがビルドされるまで 1 分ほどかかります。
ビルドの後、[エクスプローラー] に、新しいプロジェクトの場所が表示されます。 ただし、これを開く必要はありません。次のいくつかの章で、最初に他の Unity プロジェクトを作成する必要があるためです。
第 12 章 - Mixed Reality Unity プロジェクトを設定する
次に示すのは、Mixed Reality で開発するための一般的な設定であり、他のプロジェクトのテンプレートとしても適しています。
Unity を開き、[新規] をクリックします。
Unity プロジェクトに名前を付ける必要があります。「UnityMRNotifHub」と入力します。 プロジェクトの種類が [3D] に設定されていることを確認します。 [場所] を適切な場所に設定します (ルート ディレクトリに近い方が適しています)。 [Create project]\(プロジェクトの作成\) をクリックします。
Unity を開いた状態で、既定のスクリプト エディターが Visual Studio に設定されているかどうか確認することをお勧めします。 お気に入り編集>に移り、新しいウィンドウから外部ツールにナビゲートします。 [外部スクリプト エディター] を [Visual Studio 2017] に変更します。 [環境設定] ウィンドウを閉じます。
次に、ファイル>ビルド設定に移り、プラットフォーム切り替えボタンをクリックすることで、プラットフォームをユニバーサルWindowsプラットフォームに切り替えます。
[File] (ファイル)>[Build Settings] (ビルド設定) に移動して、次を確認します。
[Target Device] (ターゲット デバイス) が [Any Device] (任意のデバイス) に設定されている
Microsoft HoloLens の場合は、[ターゲット デバイス] を [HoloLens] に設定します。
[Build Type] (ビルドの種類) が [D3D] に設定されている
[SDK] が [最新のインストール] に設定されている。
[Visual Studio Version] (Visual Studio のバージョン) が [Latest installed] (最新のインストール) に設定されている
[Build and Run] (ビルドと実行) が [Local Machine] (ローカル マシン) に設定されている
ここで、シーンを保存し、ビルドに追加することをお勧めします。
これを行うには、[Add Open Scenes] (開いているシーンを追加) を選択します。 保存ウィンドウが表示されます。
これと、今後のシーン用の新しいフォルダーを作成し、[新しいフォルダー] ボタンを選択して、新しいフォルダーを作成し、「Scenes」という名前を付けます。
新しく作成した Scenes フォルダーを開き、[ファイル名] テキスト フィールドに「NH_MR_Scene」と入力して [保存] をクリックします。
[ビルド設定] の残りの設定は、ここでは既定値のままにしておきます。
同じウィンドウで、[Player Settings] (プレーヤー設定) ボタンをクリックすると、[Inspector] (インスペクター) が配置されているスペースに関連パネルが開かれます。
このパネルでは、いくつかの設定を確認する必要があります。
[Other Settings] (その他の設定) タブで、次の内容を確認します。
[Scripting Runtime Version] (スクリプト ランタイムのバージョン) が [Experimental (.NET 4.6 Equivalent)] (試験段階 (.NET 4.6 と同等)) になっている
[Scripting Backend] (スクリプト バックエンド) が [.NET] である
[API Compatibility Level]\(API 互換性レベル\) が [.NET 4.6] である。
さらに、パネルの下にある [XR Settings]\(XR 設定\) ([Publish Settings]\(公開設定\) の下) で、[Virtual Reality Supported]\(Virtual Reality サポート\) をオンにし、Windows Mixed Reality SDK が追加されていることを確認します。
[Publishing Settings]\(公開設定\) タブ内の [Capabilities]\(機能\) で、次の内容を確認します。
InternetClient
[ビルド設定] に戻ると、"Unity C# プロジェクト" に適用されていた灰色表示が解除されています。その横にあるチェック ボックスをオンにします。
これらの変更を加えた後、[Build Settings] (ビルド設定) ウィンドウを閉じます。
シーンとプロジェクトを保存します ([File] (ファイル)>[Save Scene / File] (シーン/ファイルの保存)>[Save Project] (プロジェクトの保存))。
重要
このプロジェクト (Mixed Reality アプリ)で "Unity のセットアップ" コンポーネントをスキップして、そのままコードに進みたい場合は、この .unitypackage をダウンロードして、カスタム パッケージとしてプロジェクトにインポートしてから、第 14 章から続けてください。 その場合でも、スクリプト コンポーネントを追加する必要があります。
第 13 章 - Mixed Reality Unity プロジェクトで DLL をインポートする
Azure Storage for Unity ライブラリ (.Net SDK for Azure を利用) を使用します。 Unity で Azure Storage を使用する方法についてはこちらのリンクを参照してください。 現在、Unity には、インポート後にプラグインを再構成する必要がある既知の問題があります。 バグが解決された後は、これらの手順 (このセクションの 4 - 7) は不要になります。
SDK を独自のプロジェクトにインポートするには、最新の .unitypackage がダウンロードされていることを確認してください。 次に、以下を実行します。
前述の場所からダウンロードした .unitypackage を Unity に追加するには、[Assets] (資産)>[Import Package] (パッケージのインポート)>[Custom Package] (カスタム パッケージ) メニュー オプションを使用します。
ポップアップ表示される [Import Unity Package] (Unity パッケージのインポート) ボックスで、[Plugin] (プラグイン)>[Storage] (ストレージ) の下にあるすべてを選択できます。
[Import]\(インポート\) ボタンをクリックして、各項目をプロジェクトに追加します。
[Project] (プロジェクト) ビューの [Plugins] (プラグイン) の下の Storage フォルダーに移動して、以下のプラグイン "のみ"を選択します。
- Microsoft.Data.Edm
- Microsoft.Data.OData
- Microsoft.WindowsAzure.Storage
- Newtonsoft.Json
- System.Spatial
これらのプラグイン選択した状態でuncheck Any Platform と uncheck WSAPlayer Apply をクリックします。
Note
Unity エディターで使用するためにのみこれらの特定のプラグインをマークしています。 これは、プロジェクトが Unity からエクスポートされた後に使用される、同じプラグインの異なるバージョンが WSA フォルダー内にあるためです。
Storage プラグイン フォルダーで、以下のみを選択します。
Microsoft.Data.Services.Client
[Platform Settings] (プラットフォームの設定) の下の [Don't Process] (処理しない) ボックスをオンにして、[Apply] (適用) をクリックします。
Note
Unity アセンブリ パッチャはこのプラグインを処理するのが困難であるため、このプラグインを [Don't Process] (処理しない) としてマークしています。 処理されていなくてもこのプラグインは動作します。
第 14 章 - Mixed Reality Unity プロジェクトで TableToScene クラスを作成する
TableToScene クラスは、第 9 章で説明したものと同じです。 第 9 章で説明されている手順に従って、Mixed Reality Unity プロジェクトで同じクラスを作成します。
この章を完了すると、両方の Unity プロジェクトの Main Camera にこのクラスが設定されます。
第 15 章 - Mixed Reality Unity プロジェクトで NotificationReceiver クラスを作成する
作成する必要がある 2 番目のスクリプトは NotificationReceiver です。これは次の役割を担います。
- 初期化時にアプリを Notification Hub に登録します。
- Notification Hub からの通知をリッスンします。
- 受信した通知からオブジェクト データを逆シリアル化します。
- 逆シリアル化されたデータに基づいて、シーン内の GameObjects を移動します。
NotificationReceiver スクリプトを作成するには、次のようにします。
Scripts フォルダー内で右クリックし、[Create] (作成)、[C# Script] (C# スクリプト) をクリックします。 スクリプトに NotificationReceiver という名前を付けます。
スクリプトをダブルクリックして開きます。
次の名前空間を追加します。
//using Microsoft.WindowsAzure.Messaging; using Newtonsoft.Json; using System; using System.Collections; using UnityEngine; #if UNITY_WSA_10_0 && !UNITY_EDITOR using Windows.Networking.PushNotifications; #endif
次の変数を挿入します。
/// <summary> /// allows this class to behave like a singleton /// </summary> public static NotificationReceiver instance; /// <summary> /// Value set by the notification, new object position /// </summary> Vector3 newObjPosition; /// <summary> /// Value set by the notification, object name /// </summary> string gameObjectName; /// <summary> /// Value set by the notification, new object position /// </summary> bool notifReceived; /// <summary> /// Insert here your Notification Hub Service name /// </summary> private string hubName = " -- Insert the name of your service -- "; /// <summary> /// Insert here your Notification Hub Service "Listen endpoint" /// </summary> private string hubListenEndpoint = "-Insert your Notification Hub Service Listen endpoint-";
hubName 値を Notification Hub のサービス名に置き換え、hubListenEndpoint の値を、Azure portal の Azure Notification Hub サービスの [アクセス ポリシー] タブにあるエンドポイントの値に置き換えます (下の図を参照)。
ここで、クラスを初期化するための Start () および Awake() の各メソッドを追加します。
/// <summary> /// Triggers before initialization /// </summary> void Awake() { // static instance of this class instance = this; } /// <summary> /// Use this for initialization /// </summary> void Start() { // Register the App at launch InitNotificationsAsync(); // Begin listening for notifications StartCoroutine(WaitForNotification()); }
WaitForNotification メソッドを追加して、アプリがメイン スレッドと競合せずに Notification Hub ライブラリから通知を受け取れるようにします。
/// <summary> /// This notification listener is necessary to avoid clashes /// between the notification hub and the main thread /// </summary> private IEnumerator WaitForNotification() { while (true) { // Checks for notifications each second yield return new WaitForSeconds(1f); if (notifReceived) { // If a notification is arrived, moved the appropriate object to the new position GameObject.Find(gameObjectName).transform.position = newObjPosition; // Reset the flag notifReceived = false; } } }
次のメソッド InitNotificationAsync() により、初期化時にアプリケーションが Notification Hub サービスに登録されます。 Unity がプロジェクトをビルドできないため、コードはコメントアウトされています。 Visual Studio で Azure メッセージング Nuget パッケージをインポートするときに、コメントを削除します。
/// <summary> /// Register this application to the Notification Hub Service /// </summary> private async void InitNotificationsAsync() { // PushNotificationChannel channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync(); // NotificationHub hub = new NotificationHub(hubName, hubListenEndpoint); // Registration result = await hub.RegisterNativeAsync(channel.Uri); // If registration was successful, subscribe to Push Notifications // if (result.RegistrationId != null) // { // Debug.Log($"Registration Successful: {result.RegistrationId}"); // channel.PushNotificationReceived += Channel_PushNotificationReceived; // } }
次のハンドラー Channel_PushNotificationReceived() は、通知を受信するたびにトリガーされます。 これにより、通知が逆シリアル化されます。これは、デスクトップ アプリケーションで移動された Azure テーブル エンティティであり、MR シーン内の対応する GameObject を同じ位置に移動します。
重要
このコードは、Azure メッセージング ライブラリを参照しているため、コメントアウトされています。このライブラリは、Visual Studio 内で Nuget パッケージ マネージャーを使用して Unity プロジェクトをビルドした後に追加します。 そのため、コメントアウトされていない限り、Unity プロジェクトはビルドを実行できません。プロジェクトをビルドしてから、Unity に戻る場合は、そのコードを再びコメント化する必要があることに注意してください。
///// <summary> ///// Handler called when a Push Notification is received ///// </summary> //private void Channel_PushNotificationReceived(PushNotificationChannel sender, PushNotificationReceivedEventArgs args) //{ // Debug.Log("New Push Notification Received"); // // if (args.NotificationType == PushNotificationType.Raw) // { // // Raw content of the Notification // string jsonContent = args.RawNotification.Content; // // // Deserialise the Raw content into an AzureTableEntity object // AzureTableEntity ate = JsonConvert.DeserializeObject<AzureTableEntity>(jsonContent); // // // The name of the Game Object to be moved // gameObjectName = ate.RowKey; // // // The position where the Game Object has to be moved // newObjPosition = new Vector3((float)ate.X, (float)ate.Y, (float)ate.Z); // // // Flag thats a notification has been received // notifReceived = true; // } //}
Unity エディターに戻る前に、変更内容を忘れずに保存してください。
[Hierarchy] (階層) パネルから [Main Camera] (メイン カメラ) をクリックして、そのプロパティが [Inspector] (インスペクター) に表示されるようにします。
Scripts フォルダーを開いた状態で、NotificationReceiver スクリプトを選択し、Main Camera にドラッグします。 結果は次のようになります。
Note
これを Microsoft HoloLens 向けに開発する場合、Main Camera の "カメラ" コンポーネントを次のように更新する必要があります。
- クリア フラグ: 単色
- 背景:Black
第 16 章 - Mixed Reality プロジェクトを UWP にビルドする
この章は、前のプロジェクトのビルド プロセスと同じです。 このプロジェクトの Unity セクションに必要なすべての手順が完了したため、ここでは Unity からビルドを行います。
[Build Settings] (ビルド設定) に移動します ([File] (ファイル)>[Build Settings] (ビルド設定))。
[Build Settings] (ビルド設定) メニューから、[Unity C# Projects] (Unity C# プロジェクト)* がチェックされていることを確認します (ビルド後にこのプロジェクトのスクリプトを編集できるようになります)。
完了したら、[Build] (ビルド) をクリックします。
[エクスプローラー] ウィンドウがポップアップ表示され、ビルドの場所を入力するように求められます。 新しいフォルダーを作成し (左上隅の [New Folder]\(新規フォルダー\) をクリックします)、それに BUILDS という名前を付けます。
新しい BUILDS フォルダーを開き、フォルダーをもう 1 つ作成し ([新しいフォルダー] をもう一度使用します)、NH_MR_App という名前を付けます。
NH_MR_App を選択した状態で、 [フォルダーの選択] をクリックします。 プロジェクトがビルドされるまで 1 分ほどかかります。
ビルドの後、新しいプロジェクトの場所に [エクスプローラー] ウィンドウが開きます。
第 17 章 - UnityMRNotifHub ソリューションに NuGet パッケージを追加する
警告
次の NuGet パッケージを追加 (さらに、次の章でコードをコメント解除) すると、Unity プロジェクトで再び開いたときに、コードにエラーが表示されることに注意してください。 Unity エディターに戻って編集を続ける場合は、そのエラーが発生したコードをコメント化し、Visual Studio に戻ったら後でもう一度コメントを解除する必要があります。
Mixed Reality のビルドが完了したら、ビルドした Mixed Reality プロジェクトに移動し、そのフォルダー内のソリューション (.sln) ファイルをダブルクリックして、Visual Studio 2017 でソリューションを開きます。 ここで、WindowsAzure.Messaging.managed NuGet パッケージを追加する必要があります。これは、Notification Hub から通知を受信するために使用されるライブラリです。
NuGet パッケージをインポートするには、次のようにします。
ソリューション エクスプローラーでソリューションを右クリックします。
[NuGet パッケージの管理] をクリックします。
[参照] タブを選択し、WindowsAzure.Messaging.managed を検索します。
結果 (下図参照) を選択し、右側のウィンドウで、[プロジェクト] の横にあるチェック ボックスを選択します。 これにより、[Assembly-CSharp] プロジェクトと [UnityMRNotifHub] プロジェクトの横にあるチェック ボックスと共に、[プロジェクト] の横にあるチェック ボックスにチェックマークが付きます。
最初に提供されたバージョンは、このプロジェクトと互換性がない可能性があります。 そのため、[バージョン] の横にあるドロップダウン メニューをクリックし、[バージョン 0.1.7.9] をクリックしてから [インストール] をクリックします。
これで、NuGet パッケージのインストールが完了しました。 NotificationReceiver クラスに入力したコメント付きコードを見つけて、コメントを解除します。
第 18 章 - UnityMRNotifHub アプリケーション、NotificationReceiver クラスを編集する
NuGet パッケージを追加したら、NotificationReceiver クラス内のいくつかのコードを "コメント解除" する必要があります。
これには、次のものが含まれます。
上部の名前空間:
using Microsoft.WindowsAzure.Messaging;
InitNotificationsAsync() メソッド内のすべてのコード:
/// <summary> /// Register this application to the Notification Hub Service /// </summary> private async void InitNotificationsAsync() { PushNotificationChannel channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync(); NotificationHub hub = new NotificationHub(hubName, hubListenEndpoint); Registration result = await hub.RegisterNativeAsync(channel.Uri); // If registration was successful, subscribe to Push Notifications if (result.RegistrationId != null) { Debug.Log($"Registration Successful: {result.RegistrationId}"); channel.PushNotificationReceived += Channel_PushNotificationReceived; } }
警告
上記のコードにはコメントがあります。このコメントは誤って "コメント解除" しないようにします (解除するとコードがコンパイルされません)。
最後に、Channel_PushNotificationReceived イベント:
/// <summary> /// Handler called when a Push Notification is received /// </summary> private void Channel_PushNotificationReceived(PushNotificationChannel sender, PushNotificationReceivedEventArgs args) { Debug.Log("New Push Notification Received"); if (args.NotificationType == PushNotificationType.Raw) { // Raw content of the Notification string jsonContent = args.RawNotification.Content; // Deserialize the Raw content into an AzureTableEntity object AzureTableEntity ate = JsonConvert.DeserializeObject<AzureTableEntity>(jsonContent); // The name of the Game Object to be moved gameObjectName = ate.RowKey; // The position where the Game Object has to be moved newObjPosition = new Vector3((float)ate.X, (float)ate.Y, (float)ate.Z); // Flag thats a notification has been received notifReceived = true; } }
これらがコメント解除されたら、必ず保存してから次の章に進みます。
第 19 章 - Mixed Reality プロジェクトをストア アプリに関連付ける
次に、ラボの最初に作成したストア アプリに Mixed Reality プロジェクトを関連付ける必要があります。
ソリューションを開きます。
ソリューション エクスプローラーのパネルで UWP アプリ プロジェクトを右クリックし、[ストア] に移動し、[アプリケーションをストアと関連付ける...] に移動します。
[アプリケーションを Windows ストアと関連付ける] という名前の新しいウィンドウが表示されます。 次へ をクリックします。
ログインしたアカウントに関連付けられているすべてのアプリケーションが読み込まれます。 アカウントにログインしていない場合は、このページでログインできます。
このチュートリアルの最初に作成したストア アプリ名を見つけて選択します。 続けて、 [次へ] をクリックします。
[関連付け] をクリックします。
これで、アプリがストア アプリに関連付けられます。 これは、通知を有効にするために必要です。
第 20 章 - UnityMRNotifHub および UnityDesktopNotifHub アプリケーションをデプロイする
この章では、1 つがコンピューター デスクトップで、もう 1 つがイマーシブ ヘッドセットで実行されて、結果的に両方のアプリが実行されるため、2 人で行う方が簡単かもしれません。
イマーシブ ヘッドセット アプリは、シーンに対する変更 (ローカル GameObject の位置の変更) を受け取るのを待機しています。デスクトップ アプリはローカル シーン (位置の変更) に変更を加え、それが MR アプリと共有されます。 受信側がリッスンを開始できるように、最初に MR アプリ、次にデスクトップ アプリをデプロイすることが適切です。
ローカル コンピューターに UnityMRNotifHub アプリをデプロイするには、次のようにします。
UnityMRNotifHub アプリのソリューション ファイルを Visual Studio 2017 で開きます。
ソリューションプラットフォームで、x86、ローカルマシンを選択します。
[ソリューション構成] で、[デバッグ] を選択します。
[ビルド] メニューの [ソリューションの配置] をクリックして、アプリケーションをお使いのコンピューターにサイドロードします。
ここで、インストールされたアプリのリストにアプリが現れ、起動できる状態になります。
ローカル コンピューターに UnityDesktopNotifHub アプリをデプロイするには、次のようにします。
UnityDesktopNotifHub アプリのソリューション ファイルを Visual Studio 2017 で開きます。
ソリューションプラットフォームで、x86、ローカルマシンを選択します。
[ソリューション構成] で、[デバッグ] を選択します。
[ビルド] メニューの [ソリューションの配置] をクリックして、アプリケーションをお使いのコンピューターにサイドロードします。
ここで、インストールされたアプリのリストにアプリが現れ、起動できる状態になります。
Mixed Reality アプリケーションを起動し、続いてデスクトップ アプリケーションを起動します。
両方のアプリケーションが実行されている状態で、(マウスの左ボタンを使用して) デスクトップ シーン内のオブジェクトを動かします。 これらの位置の変更は、ローカルで行われ、シリアル化されて、Function App サービスに送信されます。 Function App サービスは、Notification Hub と共にテーブルを更新します。 更新を受信すると、Notification Hub は、登録されているすべてのアプリケーション (この場合はイマーシブ ヘッドセット アプリ) に更新されたデータを直接送信します。その後、アプリケーションでは、受信データが逆シリアル化され、新しい位置データがローカル オブジェクトに適用され、シーン内で移動されます。
完成した Azure Notification Hubs アプリケーション
おめでとうございます。Azure Notification Hubs サービスを活用し、アプリ間の通信を可能にした Mixed Reality アプリを構築しました。
ボーナス演習
演習 1
GameObjects の色を変更し、シーンを表示している他のアプリにその通知を送信するにはどのようにすればいいですか。
演習 2
GameObjects の動きを MR アプリに追加し、更新されたシーンをデスクトップ アプリで確認できますか。