HoloLens (第 1 世代) と Azure 311 - Microsoft Graph
注:
Mixed Reality Academy のチュートリアルは、HoloLens (第 1 世代) と Mixed Realityイマーシブ ヘッドセットを念頭に置いて設計されました。 そのため、これらのデバイスの開発に関するガイダンスをまだ探している開発者には、これらのチュートリアルを配置しておくことが重要であると考えます。 これらのチュートリアルは、HoloLens 2に使用されている最新のツールセットや相互作用では更新されません。 これらは、サポートされているデバイスでの作業を継続するために維持されます。 今後、HoloLens 2向けに開発する方法を示す新しい一連のチュートリアルが掲載されます。 この通知は、投稿時にこれらのチュートリアルへのリンクで更新されます。
このコースでは、 Microsoft Graph を使用して、Mixed Reality アプリケーション内でセキュリティで保護された認証を使用して Microsoft アカウントにログインする方法について説明します。 その後、スケジュールされた会議を取得し、アプリケーション インターフェイスに表示します。
Microsoft Graph は、Microsoft のサービスの多くにアクセスできるように設計された API のセットです。 Microsoft では、Microsoft Graph はリレーションシップによって接続されたリソースのマトリックスであると説明しています。つまり、アプリケーションは接続されているすべての種類のユーザー データにアクセスできます。 詳細については、 Microsoft Graph のページを参照してください。
開発には、ユーザーが視線入力を指示され、球体をタップするように指示されるアプリの作成が含まれます。これにより、ユーザーは Microsoft アカウントに安全にログインするように求められます。 アカウントにログインすると、ユーザーはその日にスケジュールされた会議の一覧を表示できます。
このコースを完了すると、Mixed Reality HoloLens アプリケーションが用意され、次の操作を行うことができます。
- タップ ジェスチャを使用して、オブジェクトをタップします。これにより、ユーザーは Microsoft アカウントにログインするように求められます (アプリから移動してログインし、もう一度アプリに戻ります)。
- その日にスケジュールされた会議の一覧を表示します。
アプリケーションでは、結果を設計と統合する方法はユーザー次第です。 このコースは、Azure Service と Unity プロジェクトを統合する方法を説明するように設計されています。 このコースから得た知識を使用して、Mixed Reality アプリケーションを強化するのがあなたの仕事です。
デバイスのサポート
コース | HoloLens | イマーシブ ヘッドセット |
---|---|---|
MR と Azure 311: Microsoft Graph | ✔️ |
前提条件
注:
このチュートリアルは、Unityと C# に関する基本的な経験を持つ開発者向けに設計されています。 また、このドキュメント内の前提条件と書面による指示は、執筆時点 (2018 年 7 月) にテストおよび検証された内容を表していることにも注意してください。 ツールの インストール に関する記事に記載されているように、最新のソフトウェアを自由に使用できますが、このコースの情報は、以下に示すソフトウェアよりも新しいソフトウェアで見つかるものと完全に一致するとは想定しないでください。
このコースでは、次のハードウェアとソフトウェアをお勧めします。
- 開発用 PC
- 開発者モードが有効になっているWindows 10 Fall Creators Update (またはそれ以降)
- 最新のWindows 10 SDK
- Unity 2017.4
- Visual Studio 2017
- 開発者モードが有効になっているMicrosoft HoloLens
- Azure セットアップと Microsoft Graph データ取得のためのインターネット アクセス
- 有効な Microsoft アカウント (個人または職場/学校)
- 同じ Microsoft アカウントを使用して、現在の日にスケジュールされたいくつかの会議
始める前に
- このプロジェクトのビルドで問題が発生しないように、このチュートリアルで説明するプロジェクトをルート フォルダーまたはほぼルート フォルダーに作成することを強くお勧めします (長いフォルダー パスがビルド時に問題を引き起こす可能性があります)。
- HoloLens を設定してテストします。 HoloLens のセットアップのサポートが必要な場合は、 HoloLens のセットアップに関する記事にアクセスしてください。
- 新しい HoloLens アプリの開発を開始するときに、調整とセンサーのチューニングを実行することをお勧めします (場合によっては、ユーザーごとにこれらのタスクを実行するのに役立つ場合があります)。
調整に関するヘルプについては、 HoloLens の調整に関する記事のリンクを参照してください。
センサーのチューニングに関するヘルプについては、 HoloLens センサーチューニングに関する記事のリンクを参照してください。
第 1 章 - アプリケーション登録ポータルでアプリを作成する
まず、 アプリケーション登録ポータルでアプリケーションを作成して登録する必要があります。
この章では、 Microsoft Graph を呼び出してアカウント コンテンツにアクセスできるようにするサービス キーも示します。
Microsoft アプリケーション登録ポータルに移動し、Microsoft アカウントでログインします。 ログインすると、 アプリケーション登録ポータルにリダイレクトされます。
[ マイ アプリケーション ] セクションで、[ アプリの追加] ボタンをクリックします。
重要
アプリケーション登録ポータルは、以前に Microsoft Graph を使用したことがあるかどうかに応じて、異なる外観を示すことができます。 次のスクリーンショットは、これらの異なるバージョンを示しています。
アプリケーションの名前を追加し、[ 作成] をクリックします。
アプリケーションが作成されると、アプリケーション メイン ページにリダイレクトされます。 アプリケーション ID をコピーし、この値を安全な場所に書き留め、コードですぐに使用します。
[プラットフォーム] セクション で 、 ネイティブ アプリケーション が表示されていることを確認します。 [プラットフォームの追加] をクリックしない場合は、[ネイティブ アプリケーション] を選択します。
同じページで下にスクロールし、[ Microsoft Graph のアクセス許可] というセクションで、アプリケーションの追加のアクセス許可を追加する必要があります。 [委任されたアクセス許可] の横にある [追加] をクリックします。
アプリケーションでユーザーの予定表にアクセスする場合は、Calendars.Read という名前のボックスをチェックし、[OK] をクリックします。
一番下までスクロールし、[ 保存 ] ボタンをクリックします。
保存が確認され、 アプリケーション登録ポータルからログアウトできます。
第 2 章 - Unity プロジェクトを設定する
Mixed Reality を使用して開発するための一般的な設定を次に示します。そのため、他のプロジェクトに適したテンプレートです。
Unityを開き、[新規] をクリックします。
Unityプロジェクト名を指定する必要があります。 MSGraphMR を挿入します。 プロジェクト テンプレートが 3D に設定されていることを確認します。 [場所] を適切な場所に設定します (ルート ディレクトリに近い方が適しています)。 次に、[ プロジェクトの作成] をクリックします。
Unity開いている場合は、既定の [スクリプト] エディターが Visual Studio に設定されていることを確認する価値があります。 [編集>Preferences] に移動し、新しいウィンドウから [外部ツール] に移動します。 [外部スクリプト] エディターを Visual Studio 2017 に変更します。 [基本設定] ウィンドウを閉じます。
[ファイル>ビルドの設定] に移動し、[ユニバーサル Windows プラットフォーム] を選択し、[プラットフォームの切り替え] ボタンをクリックして選択内容を適用します。
[File>Build Settings]\(ファイル][ビルドの設定\) に残っている間は、次の点を確認します。
ターゲット デバイスが HoloLens に設定されている
ビルドの種類が D3D に設定されている
SDK が [最新インストール済み] に設定されている
Visual Studio のバージョンが [最新インストール済み] に設定されている
ビルドと実行がローカル コンピューターに設定されている
シーンを保存し、ビルドに追加します。
これを行うには、[ 開いているシーンの追加] を選択します。 保存ウィンドウが表示されます。
このための新しいフォルダーと、将来のシーンを作成します。 [ 新しいフォルダー ] ボタンを選択して新しいフォルダーを作成し、 Scenes という名前を付けます。
新しく作成した Scenes フォルダーを開き、[ ファイル名: テキスト] フィールドに 「MR_ComputerVisionScene」と入力し、[ 保存] をクリックします。
重要
Unity プロジェクトに関連付けられている必要があるため、Unity シーンを Assets フォルダーに保存する必要があることに注意してください。 scenes フォルダー (およびその他の同様のフォルダー) を作成することは、Unity プロジェクトを構築する一般的な方法です。
[ ビルド設定] の残りの設定は、現時点では既定値のままにする必要があります。
[ ビルド設定] ウィンドウで、[ プレイヤーの設定] ボタンをクリックすると、 インスペクター が配置されている領域に関連するパネルが開きます。
このパネルでは、いくつかの設定を確認する必要があります。
[その他の設定] タブで、次 の手順を実行 します。
スクリプト ランタイムバージョンは試験的 (.NET 4.6 同等) にする必要があります。これにより、エディターを再起動する必要がトリガーされます。
スクリプト バックエンドは .NET にする必要があります
API 互換性レベルは .NET 4.6 にする必要があります
[発行設定] タブの [機能] で、次をチェックします。
InternetClient
パネルの下の [XR 設定] ([発行設定] の下にあります)、[サポートされている Virtual Reality] チェック、Windows Mixed Reality SDK が追加されていることを確認します。
ビルド設定に戻ると、C# プロジェクトUnity灰色表示されなくなります。この横にあるチェックボックスをチェックします。
[ビルド設定] ウィンドウを閉じます。
シーンとプロジェクトを保存します (FILE>SAVE SCENES/FILE>SAVE PROJECT)。
第 3 章 - Unityでのライブラリのインポート
重要
このコースのUnityセットアップ コンポーネントをスキップしてコードに直接進む場合は、この Azure-MR-311.unitypackage を自由にダウンロードし、カスタム パッケージとしてプロジェクトにインポートしてから、第 5 章から続行してください。
Unity内で Microsoft Graph を使用するには、Microsoft.Identity.Client DLL を使用する必要があります。 Microsoft Graph SDK を使用することはできますが、Unity プロジェクトをビルドした後に NuGet パッケージを追加する必要があります (ビルド後のプロジェクトの編集を意味します)。 必要な DLL を直接Unityにインポートする方が簡単と見なされます。
注:
現在、Unityには、インポート後にプラグインを再構成する必要がある既知の問題があります。 バグが解決された後、これらの手順 (このセクションの 4 ~ 7) は不要になります。
Microsoft Graph を独自のプロジェクトにインポートするには、MSGraph_LabPlugins.zip ファイルをダウンロードします。 このパッケージは、テストされたライブラリのバージョンで作成されています。
Unity プロジェクトにカスタム DLL を追加する方法の詳細については、こちらのリンクを参照してください。
パッケージをインポートするには:
[Assets>Import Package>Custom Package] メニュー オプションを使用してUnityにUnity パッケージを追加します。 ダウンロードしたパッケージを選択します。
ポップアップ表示される [Unity パッケージのインポート] ボックスで、[プラグイン] の下 (および含む) がすべて選択されていることを確認します。
[ インポート ] ボタンをクリックして、項目をプロジェクトに追加します。
プロジェクト パネルの [プラグイン] の下にある MSGraph フォルダーに移動し、Microsoft.Identity.Client というプラグインを選択します。
プラグインを選択した状態で、[Any Platform]\(任意のプラットフォーム\) がオフになっていることを確認し、WSAPlayer もオフになっていることを確認し、[適用] をクリックします。 これは、ファイルが正しく構成されていることを確認するためだけです。
注:
これらのプラグインをマークすると、Unity エディターでのみ使用されるように構成されます。 WSA フォルダーには別の DLL セットがあり、プロジェクトがユニバーサル Windows アプリケーションとしてUnityからエクスポートされた後に使用されます。
次に、MSGraph フォルダー内の WSA フォルダーを開く必要があります。 構成したのと同じファイルのコピーが表示されます。 ファイルを選択し、インスペクターで次の手順を実行します。
[Any Platform]\(任意のプラットフォーム\) がオフになっていることを確認し、WSAPlayerのみがオンになっていることを確認します。
SDK が UWP に設定され、スクリプト バックエンドが Dot Net に設定されていることを確認します
[処理しない] がオンになっていることを確認します。
[適用] をクリックします。
第 4 章 - カメラのセットアップ
この章では、シーンのメイン カメラを設定します。
[階層] パネルで、メイン カメラを選択します。
選択すると、[インスペクター] パネルにメイン カメラのすべてのコンポーネントが表示されます。
Camera オブジェクトには Main Camera という名前を付ける必要があります (スペルに注意してください)。
メイン カメラ タグ は MainCamera に設定する必要があります (スペルに注意してください)。
[位置の変換] が 0、0、0 に設定されていることを確認します
[クリア フラグ] を [純色] に設定する
カメラ コンポーネントの背景色を黒、アルファ 0に設定します (16 進数コード: #000000000)
階層パネルの最後のオブジェクト構造は、次の図のようになります。
第 5 章 - MeetingsUI クラスを作成する
最初に作成する必要があるスクリプトは MeetingsUI です。これは、アプリケーションの UI (ウェルカム メッセージ、指示、会議の詳細) のホストと設定を担当します。
このクラスを作成するには:
プロジェクト パネルで [Assets] フォルダーを右クリックし、[作成>Folder] を選択します。 [スクリプト] フォルダーに名前 を付けます。
[スクリプト] フォルダーを開き、そのフォルダー内で右クリックし、[作成>C# スクリプト] をクリックします。 スクリプトに MeetingsUI という名前を付けます。
新しい MeetingsUI スクリプトをダブルクリックして 、Visual Studio で開きます。
次の名前空間を挿入します。
using System; using UnityEngine;
クラス内に次の変数を挿入します。
/// <summary> /// Allows this class to behave like a singleton /// </summary> public static MeetingsUI Instance; /// <summary> /// The 3D text of the scene /// </summary> private TextMesh _meetingDisplayTextMesh;
次に 、Start() メソッドを置き換え、 Awake() メソッドを追加します。 これらは、 クラスが初期化するときに呼び出されます。
/// <summary> /// Called on initialization /// </summary> void Awake() { Instance = this; } /// <summary> /// Called on initialization, after Awake /// </summary> void Start () { // Creating the text mesh within the scene _meetingDisplayTextMesh = CreateMeetingsDisplay(); }
会議 UI の作成を担当するメソッドを追加し、要求されたときに現在の会議を設定します。
/// <summary> /// Set the welcome message for the user /// </summary> internal void WelcomeUser(string userName) { if(!string.IsNullOrEmpty(userName)) { _meetingDisplayTextMesh.text = $"Welcome {userName}"; } else { _meetingDisplayTextMesh.text = "Welcome"; } } /// <summary> /// Set up the parameters for the UI text /// </summary> /// <returns>Returns the 3D text in the scene</returns> private TextMesh CreateMeetingsDisplay() { GameObject display = new GameObject(); display.transform.localScale = new Vector3(0.03f, 0.03f, 0.03f); display.transform.position = new Vector3(-3.5f, 2f, 9f); TextMesh textMesh = display.AddComponent<TextMesh>(); textMesh.anchor = TextAnchor.MiddleLeft; textMesh.alignment = TextAlignment.Left; textMesh.fontSize = 80; textMesh.text = "Welcome! \nPlease gaze at the button" + "\nand use the Tap Gesture to display your meetings"; return textMesh; } /// <summary> /// Adds a new Meeting in the UI by chaining the existing UI text /// </summary> internal void AddMeeting(string subject, DateTime dateTime, string location) { string newText = $"\n{_meetingDisplayTextMesh.text}\n\n Meeting,\nSubject: {subject},\nToday at {dateTime},\nLocation: {location}"; _meetingDisplayTextMesh.text = newText; }
Update() メソッドを削除し、変更を Visual Studio に保存してから、Unityに戻ります。
第 6 章 - Graph クラスを作成する
次に作成するスクリプトは Graph スクリプトです。 このスクリプトは、ユーザーを認証し、ユーザーの予定表から現在の日のスケジュールされた会議を取得するための呼び出しを行う役割を担います。
このクラスを作成するには:
Scripts フォルダーをダブルクリックして開きます。
[スクリプト] フォルダー内を右クリックし、[作成>C# スクリプト] をクリックします。 スクリプトに Graph という名前を 付けます。
スクリプトをダブルクリックして Visual Studio で開きます。
次の名前空間を挿入します。
using System.Collections.Generic; using UnityEngine; using Microsoft.Identity.Client; using System; using System.Threading.Tasks; #if !UNITY_EDITOR && UNITY_WSA using System.Net.Http; using System.Net.Http.Headers; using Windows.Storage; #endif
重要
このスクリプトのコードの一部が プリコンパイル ディレクティブにラップされていることに気付くでしょう。これは、Visual Studio ソリューションをビルドするときにライブラリの問題を回避するためです。
Start() メソッドと Update() メソッドは使用されないため、削除します。
Graph クラスの外部に次のオブジェクトを挿入します。これは、毎日スケジュールされた会議を表す JSON オブジェクトを逆シリアル化するために必要です。
/// <summary> /// The object hosting the scheduled meetings /// </summary> [Serializable] public class Rootobject { public List<Value> value; } [Serializable] public class Value { public string subject { get; set; } public StartTime start { get; set; } public Location location { get; set; } } [Serializable] public class StartTime { public string dateTime; private DateTime? _startDateTime; public DateTime StartDateTime { get { if (_startDateTime != null) return _startDateTime.Value; DateTime dt; DateTime.TryParse(dateTime, out dt); _startDateTime = dt; return _startDateTime.Value; } } } [Serializable] public class Location { public string displayName { get; set; } }
Graph クラス内に、次の変数を追加します。
/// <summary> /// Insert your Application Id here /// </summary> private string _appId = "-- Insert your Application Id here --"; /// <summary> /// Application scopes, determine Microsoft Graph accessibility level to user account /// </summary> private IEnumerable<string> _scopes = new List<string>() { "User.Read", "Calendars.Read" }; /// <summary> /// Microsoft Graph API, user reference /// </summary> private PublicClientApplication _client; /// <summary> /// Microsoft Graph API, authentication /// </summary> private AuthenticationResult _authResult;
注:
appId の値を、第 1 章の手順 4 で確認したアプリ ID に変更します。 この値は、 アプリケーション登録ポータルのアプリケーション登録 ページに表示される値と同じである必要があります。
Graph クラス内で、SignInAsync() メソッドと AquireTokenAsync()メソッドを追加します。このメソッドは、ユーザーにログイン資格情報の挿入を求めます。
/// <summary> /// Begin the Sign In process using Microsoft Graph Library /// </summary> internal async void SignInAsync() { #if !UNITY_EDITOR && UNITY_WSA // Set up Grap user settings, determine if needs auth ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings; string userId = localSettings.Values["UserId"] as string; _client = new PublicClientApplication(_appId); // Attempt authentication _authResult = await AcquireTokenAsync(_client, _scopes, userId); // If authentication is successful, retrieve the meetings if (!string.IsNullOrEmpty(_authResult.AccessToken)) { // Once Auth as been completed, find the meetings for the day await ListMeetingsAsync(_authResult.AccessToken); } #endif } /// <summary> /// Attempt to retrieve the Access Token by either retrieving /// previously stored credentials or by prompting user to Login /// </summary> private async Task<AuthenticationResult> AcquireTokenAsync( IPublicClientApplication app, IEnumerable<string> scopes, string userId) { IUser user = !string.IsNullOrEmpty(userId) ? app.GetUser(userId) : null; string userName = user != null ? user.Name : "null"; // Once the User name is found, display it as a welcome message MeetingsUI.Instance.WelcomeUser(userName); // Attempt to Log In the user with a pre-stored token. Only happens // in case the user Logged In with this app on this device previously try { _authResult = await app.AcquireTokenSilentAsync(scopes, user); } catch (MsalUiRequiredException) { // Pre-stored token not found, prompt the user to log-in try { _authResult = await app.AcquireTokenAsync(scopes); } catch (MsalException msalex) { Debug.Log($"Error Acquiring Token: {msalex.Message}"); return _authResult; } } MeetingsUI.Instance.WelcomeUser(_authResult.User.Name); #if !UNITY_EDITOR && UNITY_WSA ApplicationData.Current.LocalSettings.Values["UserId"] = _authResult.User.Identifier; #endif return _authResult; }
次の 2 つのメソッドを追加します。
BuildTodayCalendarEndpoint()。スケジュールされた会議を取得する日と期間を指定する URI を構築します。
Microsoft Graph からスケジュールされた会議を要求する ListMeetingsAsync()。
/// <summary> /// Build the endpoint to retrieve the meetings for the current day. /// </summary> /// <returns>Returns the Calendar Endpoint</returns> public string BuildTodayCalendarEndpoint() { DateTime startOfTheDay = DateTime.Today.AddDays(0); DateTime endOfTheDay = DateTime.Today.AddDays(1); DateTime startOfTheDayUTC = startOfTheDay.ToUniversalTime(); DateTime endOfTheDayUTC = endOfTheDay.ToUniversalTime(); string todayDate = startOfTheDayUTC.ToString("o"); string tomorrowDate = endOfTheDayUTC.ToString("o"); string todayCalendarEndpoint = string.Format( "https://graph.microsoft.com/v1.0/me/calendarview?startdatetime={0}&enddatetime={1}", todayDate, tomorrowDate); return todayCalendarEndpoint; } /// <summary> /// Request all the scheduled meetings for the current day. /// </summary> private async Task ListMeetingsAsync(string accessToken) { #if !UNITY_EDITOR && UNITY_WSA var http = new HttpClient(); http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); var response = await http.GetAsync(BuildTodayCalendarEndpoint()); var jsonResponse = await response.Content.ReadAsStringAsync(); Rootobject rootObject = new Rootobject(); try { // Parse the JSON response. rootObject = JsonUtility.FromJson<Rootobject>(jsonResponse); // Sort the meeting list by starting time. rootObject.value.Sort((x, y) => DateTime.Compare(x.start.StartDateTime, y.start.StartDateTime)); // Populate the UI with the meetings. for (int i = 0; i < rootObject.value.Count; i++) { MeetingsUI.Instance.AddMeeting(rootObject.value[i].subject, rootObject.value[i].start.StartDateTime.ToLocalTime(), rootObject.value[i].location.displayName); } } catch (Exception ex) { Debug.Log($"Error = {ex.Message}"); return; } #endif }
これで Graph スクリプトが完了しました。 Unityに戻る前に、変更を Visual Studio に保存します。
第 7 章 - GazeInput スクリプトを作成する
次に、 GazeInput を作成します。 このクラスは、メイン カメラから送信されるレイキャストを使用して、前方に投影して、ユーザーの視線入力を処理して追跡します。
スクリプトを作成するには:
Scripts フォルダーをダブルクリックして開きます。
[スクリプト] フォルダー内を右クリックし、[作成>C# スクリプト] をクリックします。 スクリプトに GazeInput という名前を 付けます。
スクリプトをダブルクリックして Visual Studio で開きます。
次のコードと一致するように名前空間コードを変更し、GazeInput クラスの上に '[System.Serializable]' タグを追加して、シリアル化できるようにします。
using UnityEngine; /// <summary> /// Class responsible for the User's Gaze interactions /// </summary> [System.Serializable] public class GazeInput : MonoBehaviour {
GazeInput クラス内に、次の変数を追加します。
[Tooltip("Used to compare whether an object is to be interacted with.")] internal string InteractibleTag = "SignInButton"; /// <summary> /// Length of the gaze /// </summary> internal float GazeMaxDistance = 300; /// <summary> /// Object currently gazed /// </summary> internal GameObject FocusedObject { get; private set; } internal GameObject oldFocusedObject { get; private set; } internal RaycastHit HitInfo { get; private set; } /// <summary> /// Cursor object visible in the scene /// </summary> internal GameObject Cursor { get; private set; } internal bool Hit { get; private set; } internal Vector3 Position { get; private set; } internal Vector3 Normal { get; private set; } private Vector3 _gazeOrigin; private Vector3 _gazeDirection;
CreateCursor() メソッドを追加してシーンに HoloLens カーソルを作成し、Start() メソッドから メソッドを呼び出します。
/// <summary> /// Start method used upon initialisation. /// </summary> internal virtual void Start() { FocusedObject = null; Cursor = CreateCursor(); } /// <summary> /// Method to create a cursor object. /// </summary> internal GameObject CreateCursor() { GameObject newCursor = GameObject.CreatePrimitive(PrimitiveType.Sphere); newCursor.SetActive(false); // Remove the collider, so it doesn't block raycast. Destroy(newCursor.GetComponent<SphereCollider>()); newCursor.transform.localScale = new Vector3(0.05f, 0.05f, 0.05f); Material mat = new Material(Shader.Find("Diffuse")); newCursor.GetComponent<MeshRenderer>().material = mat; mat.color = Color.HSVToRGB(0.0223f, 0.7922f, 1.000f); newCursor.SetActive(true); return newCursor; }
次のメソッドは、視線入力レイキャストを有効にし、フォーカスされたオブジェクトを追跡します。
/// <summary> /// Called every frame /// </summary> internal virtual void Update() { _gazeOrigin = Camera.main.transform.position; _gazeDirection = Camera.main.transform.forward; UpdateRaycast(); } /// <summary> /// Reset the old focused object, stop the gaze timer, and send data if it /// is greater than one. /// </summary> private void ResetFocusedObject() { // Ensure the old focused object is not null. if (oldFocusedObject != null) { if (oldFocusedObject.CompareTag(InteractibleTag)) { // Provide the 'Gaze Exited' event. oldFocusedObject.SendMessage("OnGazeExited", SendMessageOptions.DontRequireReceiver); } } }
private void UpdateRaycast() { // Set the old focused gameobject. oldFocusedObject = FocusedObject; RaycastHit hitInfo; // Initialise Raycasting. Hit = Physics.Raycast(_gazeOrigin, _gazeDirection, out hitInfo, GazeMaxDistance); HitInfo = hitInfo; // Check whether raycast has hit. if (Hit == true) { Position = hitInfo.point; Normal = hitInfo.normal; // Check whether the hit has a collider. if (hitInfo.collider != null) { // Set the focused object with what the user just looked at. FocusedObject = hitInfo.collider.gameObject; } else { // Object looked on is not valid, set focused gameobject to null. FocusedObject = null; } } else { // No object looked upon, set focused gameobject to null. FocusedObject = null; // Provide default position for cursor. Position = _gazeOrigin + (_gazeDirection * GazeMaxDistance); // Provide a default normal. Normal = _gazeDirection; } // Lerp the cursor to the given position, which helps to stabilize the gaze. Cursor.transform.position = Vector3.Lerp(Cursor.transform.position, Position, 0.6f); // Check whether the previous focused object is this same. If so, reset the focused object. if (FocusedObject != oldFocusedObject) { ResetFocusedObject(); if (FocusedObject != null) { if (FocusedObject.CompareTag(InteractibleTag)) { // Provide the 'Gaze Entered' event. FocusedObject.SendMessage("OnGazeEntered", SendMessageOptions.DontRequireReceiver); } } } }
Unityに戻る前に、変更を Visual Studio に保存します。
第 8 章 - Interactions クラスを作成する
次に、次の役割を担 う Interactions スクリプトを作成する必要があります。
タップ操作とカメラの視線入力を処理します。これにより、ユーザーはシーン内の "ボタン" でログを操作できます。
ユーザーが操作できるように、シーン内の "ボタン" オブジェクトにログを作成します。
スクリプトを作成するには:
Scripts フォルダーをダブルクリックして開きます。
[スクリプト] フォルダー内を右クリックし、[作成>C# スクリプト] をクリックします。 スクリプトに Interactions という名前を付けます。
スクリプトをダブルクリックして Visual Studio で開きます。
次の名前空間を挿入します。
using UnityEngine; using UnityEngine.XR.WSA.Input;
Interaction クラスの継承を MonoBehaviour から GazeInput に変更します。
public クラスの相互作用 : MonoBehaviourpublic class Interactions : GazeInput
Interaction クラス内に、次の変数を挿入します。
/// <summary> /// Allows input recognition with the HoloLens /// </summary> private GestureRecognizer _gestureRecognizer;
Start メソッドを置き換えます。これはオーバーライド メソッドであり、'base' Gaze クラス メソッドを呼び出します。 Start() は、クラスの初期化時に呼び出され、入力認識に登録され、シーンにサインイン ボタン が作成されます。
/// <summary> /// Called on initialization, after Awake /// </summary> internal override void Start() { base.Start(); // Register the application to recognize HoloLens user inputs _gestureRecognizer = new GestureRecognizer(); _gestureRecognizer.SetRecognizableGestures(GestureSettings.Tap); _gestureRecognizer.Tapped += GestureRecognizer_Tapped; _gestureRecognizer.StartCapturingGestures(); // Add the Graph script to this object gameObject.AddComponent<MeetingsUI>(); CreateSignInButton(); }
CreateSignInButton() メソッドを追加します。これにより、シーン内のサインイン ボタンがインスタンス化され、そのプロパティが設定されます。
/// <summary> /// Create the sign in button object in the scene /// and sets its properties /// </summary> void CreateSignInButton() { GameObject signInButton = GameObject.CreatePrimitive(PrimitiveType.Sphere); Material mat = new Material(Shader.Find("Diffuse")); signInButton.GetComponent<Renderer>().material = mat; mat.color = Color.blue; signInButton.transform.position = new Vector3(3.5f, 2f, 9f); signInButton.tag = "SignInButton"; signInButton.AddComponent<Graph>(); }
Tap ユーザー イベントに応答する GestureRecognizer_Tapped() メソッドを追加します。
/// <summary> /// Detects the User Tap Input /// </summary> private void GestureRecognizer_Tapped(TappedEventArgs obj) { if(base.FocusedObject != null) { Debug.Log($"TAP on {base.FocusedObject.name}"); base.FocusedObject.SendMessage("SignInAsync", SendMessageOptions.RequireReceiver); } }
Update() メソッドを削除し、変更を Visual Studio に保存してから、Unityに戻ります。
第 9 章 - スクリプト参照を設定する
この章では、 操作 スクリプトを メイン カメラに配置する必要があります。 その後、そのスクリプトは、必要な場所に他のスクリプトを配置します。
次に示すように、プロジェクト パネルの [スクリプト] フォルダーから、スクリプトの [相互作用] を Main Camera オブジェクトにドラッグします。
第 10 章 - タグの設定
視線入力を処理するコードでは、Tag SignInButton を使用して、 ユーザーが Microsoft Graph にサインインするために操作するオブジェクトを識別します。
タグを作成するには:
Unity エディターで、[階層] パネルの [メイン カメラ] をクリックします。
[インスペクター] パネルで MainCameraタグをクリックして、ドロップダウン リストを開きます。 [タグの追加]をクリック します。..
[ + ] ボタンをクリックします。
タグ名を SignInButton として書き込み、[保存] をクリックします。
第 11 章 - Unity プロジェクトを UWP にビルドする
このプロジェクトのUnityセクションに必要なものはすべて完了したので、Unityからビルドします。
[ビルド設定] ([ファイル] >[ビルド設定] ) に移動します。
まだない場合は、[C# プロジェクト] Unityチェック ボックスをオンにします。
[ ビルド] をクリックします。 Unityはエクスプローラー ウィンドウを起動します。ここで、アプリをビルドするフォルダーを作成して選択する必要があります。 そのフォルダーを今すぐ作成し、App という名前 を付けます。 次に、[ アプリ ] フォルダーが選択された状態で、[ フォルダーの選択] をクリックします。
Unityは、App フォルダーへのプロジェクトのビルドを開始します。
ビルドUnity完了すると (時間がかかる場合があります)、ビルドの場所にエクスプローラー ウィンドウが開きます (タスク バーチェック、常にウィンドウの上に表示されるとは限りませんが、新しいウィンドウが追加されたことを通知します)。
第 12 章 - HoloLens へのデプロイ
HoloLens にデプロイするには:
HoloLens の IP アドレス (リモート展開用) と、HoloLens が 開発者モード であることを確認する必要があります。これを行うには:
HoloLens を装着している間に 、[設定] を開きます。
[ネットワーク & インターネット>Wi-Fi>Advanced Options] に移動します
IPv4 アドレスをメモします。
次に、[ 設定] に戻り、[ Update & Security>For Developers
[開発者モード] を [オン] に設定します。
新しいUnity ビルド (App フォルダー) に移動し、Visual Studio でソリューション ファイルを開きます。
[ソリューション構成] で [デバッグ] を選択します。
ソリューション プラットフォームで、x86 リモート マシンを選択します。 リモート デバイスの IP アドレス を挿入するように求められます (この場合は、メモした HoloLens)。
[ビルド] メニューに移動し、[ソリューションの展開] をクリックして、アプリケーションを HoloLens にサイドロードします。
これで、HoloLens にインストールされているアプリの一覧にアプリが表示され、起動する準備が整いました。
Microsoft Graph HoloLens アプリケーション
これで、Microsoft Graph を利用してユーザーの予定表データを読み取って表示する Mixed Reality アプリが構築されました。
ボーナス演習
演習 1
Microsoft Graph を使用してユーザーに関するその他の情報を表示する
- ユーザーメール/電話番号/プロフィール画像
演習 1
音声コントロールを実装して、Microsoft Graph UI を移動します。