HoloLens (第 1 代) 和 Azure 308:跨裝置通知
注意
混合實境學院教學課程的設計是以 HoloLens (第 1 代) 和混合實境沉浸式頭戴裝置為準。 因此,對於仍在尋找這些裝置開發指引的開發人員而言,我們覺得這些教學課程很重要。 這些教學課程不會使用用於 HoloLens 2 的最新工具組或互動進行更新。 系統會保留這些資訊,以繼續在支援的裝置上運作。 未來將會張貼一系列新的教學課程,以示範如何為 HoloLens 2 進行開發。 張貼這些教學課程的連結將會更新此通知。
在此課程中,您將瞭解如何使用 Azure 通知中樞、Azure 數據表和 Azure Functions,將通知中樞功能新增至混合實境應用程式。
Azure 通知中 樞是一項Microsoft服務,可讓開發人員將針對性和個人化的推播通知傳送至雲端內所有平臺。 這可讓開發人員根據案例,有效地與終端用戶通訊,或甚至是在各種應用程式之間進行通訊。 如需詳細資訊,請流覽 Azure 通知中樞頁面。
Azure Functions 是一項Microsoft服務,可讓開發人員在 Azure 中執行小型程式代碼「函式」。 這提供將工作委派給雲端的方式,而不是您的本機應用程式,這有許多優點。 Azure Functions 支援數種開發語言,包括 C#、F#、Node.js、Java 和 PHP。 如需詳細資訊,請流覽 Azure Functions 頁面。
Azure 數據表 是一項Microsoft雲端服務,可讓開發人員將結構化的非 SQL 資料儲存在雲端中,使其可在任何地方輕鬆存取。 此服務擁有無架構設計,可視需要演進數據表,因此非常有彈性。 如需詳細資訊,請流覽 Azure 數據表頁面
完成本課程之後,您將有混合實境沉浸式頭戴式裝置應用程式,以及桌面計算機應用程式,其可以執行下列動作:
桌面電腦應用程式可讓使用者使用滑鼠在 2D 空間 (X 和 Y) 中移動物件。
計算機應用程式內的物件移動將會使用 JSON 傳送至雲端,其格式為字串,其中包含物件識別碼、類型和轉換資訊(X 和 Y 座標)。
混合實境應用程式與傳統型應用程式具有相同場景,將會從通知中樞服務收到有關物件移動的通知(桌面計算機應用程式剛剛更新過)。
收到通知時,其中包含物件標識碼、類型和轉換資訊,混合實境應用程式會將接收的資訊套用至自己的場景。
在您的應用程式中,您應該瞭解如何將結果與設計整合。 本課程旨在教導您如何整合 Azure 服務與 Unity 專案。 使用本課程中取得的知識來增強混合實境應用程式,是您的工作。 本課程是獨立的教學課程,不會直接涉及任何其他混合實境實驗室。
裝置支援
課程 | HoloLens | 沉浸式頭戴裝置 |
---|---|---|
MR 和 Azure 308:跨裝置通知 | ✔️ | ✔️ |
注意
雖然本課程主要著重於 Windows Mixed Reality 沉浸式 (VR) 頭戴式裝置,但您也可以將此課程中學到的內容套用至 Microsoft HoloLens。 隨著您遵循課程,您將會看到任何您可能需要採用以支援 HoloLens 變更的附注。 使用 HoloLens 時,您可能會在語音擷取期間注意到一些回應。
必要條件
注意
本教學課程專為具備 Unity 和 C# 基本經驗的開發人員所設計。 另請注意,本檔內的必要條件和書面指示代表在撰寫期間經過測試和驗證的內容(2018 年 5 月)。 您可以自由使用最新的軟體,如安裝工具文章中所列,不過不應該假設本課程中的資訊會完全符合您在較新的軟體中找到的內容,而不是下面所列的內容。
針對此課程,我們建議使用下列硬體和軟體:
- 開發計算機, 與 Windows Mixed Reality 相容以進行沉浸式 (VR) 頭戴式裝置開發
- 已啟用開發人員模式的 Windows 10 Fall Creators Update (或更新版本)
- 最新的 Windows 10 SDK
- Unity 2017.4
- Visual Studio 2017
- 已啟用開發人員模式的 Windows Mixed Reality 沉浸式 (VR) 頭戴式裝置或Microsoft HoloLens
- Azure 設定和存取通知中樞的因特網存取
在您開始使用 Intune 之前
- 為了避免建置此專案時發生問題,強烈建議您在根資料夾或近根資料夾中建立本教學課程中所提及的專案(長文件夾路徑在建置時可能會導致問題)。
- 您必須是Microsoft開發人員入口網站和應用程式註冊入口網站的擁有者,否則您將無權存取第 2 章中的應用程式。
第 1 章 - 在 Microsoft 開發人員入口網站上建立應用程式
若要使用 Azure 通知中樞 服務,您必須在Microsoft開發人員入口網站上建立應用程式,因為您的應用程式必須註冊,才能傳送和接收通知。
-
您必須登入Microsoft帳戶。
從 [儀錶板] 中,按兩下 [建立新的應用程式]。
彈出視窗隨即出現,您需要為新的應用程式保留名稱。 在文字框中,插入適當的名稱;如果所選的名稱可用,則文字框右側會出現刻度。 插入可用的名稱之後,請按下快顯左下方的 [ 保留產品名稱 ] 按鈕。
現在已建立應用程式之後,您就可以移至下一章。
第 2 章 - 擷取新的應用程式認證
登入應用程式註冊入口網站,其中會列出您的新應用程式,並擷取將用來在 Azure 入口網站中設定通知中樞服務的認證。
瀏覽至應用程式 註冊入口網站。
警告
您必須使用Microsoft帳戶登入。
這 必須是 您在上 一章中用來搭配 Windows 市集開發人員入口網站使用的Microsoft帳戶。您會在 [ 我的應用程式 ] 區段下找到您的應用程式。 找到它之後,按兩下它,系統會帶您前往具有應用程式名稱加上 註冊的新頁面。
向下卷動註冊頁面,以尋找您的應用程式的應用程式秘密區段和套件 SID。 複製這兩者以用於設定 下一章中的 Azure 通知中樞服務 。
第 3 章 - 設定 Azure 入口網站:建立通知中樞服務
在擷取應用程式認證之後,您必須移至 Azure 入口網站,您可以在其中建立 Azure 通知中樞服務。
登入 Azure 入口網站。
注意
如果您還沒有 Azure 帳戶,則必須建立一個帳戶。 如果您在教室或實驗室情況中遵循本教學課程,請洽詢您的講師或其中一名監看員,以協助設定您的新帳戶。
登入之後,按兩下左上角的 [新增],然後搜尋通知中樞,然後按兩下 Enter。
注意
[新增] 一詞可能已取代為在較新的入口網站中建立資源。
新頁面將提供通知中 樞 服務的描述。 在此提示的左下角,選取 [ 建立] 按鈕,以建立與這項服務的關聯。
按兩下 [建立]:
插入此服務實例所需的名稱。
提供命名空間,讓您可以與此應用程式產生關聯。
選取 [位置] 。
選擇資源群組或建立新的群組。 資源群組提供一種方式來監視、控制存取、布建和管理 Azure 資產集合的計費。 建議將所有與單一專案相關聯的 Azure 服務(例如,例如這些實驗室)保留在通用資源群組之下。
如果您想要深入瞭解 Azure 資源群組,請遵循此 連結以瞭解如何管理資源群組。
選取適當的訂用 帳戶。
您也必須確認您已瞭解此服務適用的條款和條件。
選取 建立。
按兩下 [ 建立] 之後,您必須等候服務建立,這可能需要一分鐘的時間。
建立服務實例之後,入口網站中就會顯示通知。
按兩下通知中的 [ 移至資源 ] 按鈕,以探索新的服務實例。 系統會帶您前往新的 通知中樞 服務實例。
從概觀頁面的下半部按兩下 [Windows] (WNS)。 右側的面板將會變更,以顯示兩個文字欄位,其需要您 先前設定的應用程式的套件 SID 和安全性 金鑰。
將詳細數據複製到正確的欄位之後,按兩下 [儲存],當通知中樞成功更新時,您會收到通知。
第 4 章 - 設定 Azure 入口網站:建立數據表服務
建立通知中樞服務實例之後,請流覽回您的 Azure 入口網站,您可以在其中建立記憶體資源來建立 Azure 數據表服務。
如果尚未登入,請登入 Azure 入口網站。
登入之後,按兩下左上角的 [ 新增 ],然後搜尋 記憶體帳戶,然後按兩下 Enter。
注意
[新增] 一詞可能已取代為在較新的入口網站中建立資源。
從清單中選取 [儲存體帳戶 - Blob、檔案、數據表、佇列 ]。
新頁面將提供記憶體帳戶服務的描述。 在此提示的左下方,選取 [ 建立] 按鈕,以建立此服務的實例。
按兩下 [ 建立] 之後,會出現面板:
插入此服務實例所需的 名稱 (必須是全部小寫)。
針對 [部署模型],按兩下 [資源管理員]。
針對 [帳戶種類],使用下拉功能表,選取 [記憶體](一般用途 v1)。
選取適當的 [位置]。
針對 [復寫] 下拉功能表,選取 [讀取存取- 異地備援記憶體 ][RA-GRS]。
針對 [效能],按兩下 [ 標準]。
在 [ 需要安全傳輸] 區段中,選取 [ 已停用]。
從 [ 訂用帳戶] 下拉功能表中,選取適當的訂用帳戶。
選擇資源群組或建立新的群組。 資源群組提供一種方式來監視、控制存取、布建和管理 Azure 資產集合的計費。 建議將所有與單一專案相關聯的 Azure 服務(例如,例如這些實驗室)保留在通用資源群組之下。
如果您想要深入瞭解 Azure 資源群組,請遵循此 連結以瞭解如何管理資源群組。
如果這是您的選項,請將虛擬網路保留為 [已停用]。
按一下 [建立]。
按兩下 [ 建立] 之後,您必須等候服務建立,這可能需要一分鐘的時間。
建立服務實例之後,入口網站中就會顯示通知。 按兩下通知以探索新的服務實例。
按兩下通知中的 [ 移至資源 ] 按鈕,以探索新的服務實例。 系統會帶您前往新的記憶體服務實例概觀頁面。
從概觀頁面到右側,按兩下 [ 數據表]。
右側的面板將會變更以顯示 資料表服務 資訊,您需要在其中新增數據表。 按兩下左上角的 + [資料表] 按鈕來執行此動作。
隨即會顯示新的頁面,其中您需要輸入 數據表名稱。 這是您將用來在稍後章節中參考應用程式中數據的名稱。 插入適當的名稱,然後按兩下 [ 確定]。
建立新的資料表之後,您就可以在 [數據表服務 ] 頁面 (底部) 中看到它。
第 5 章 - 在 Visual Studio 中完成 Azure 數據表
現在已設定數據表 服務 記憶體帳戶,現在可以將數據加入其中,以用來儲存和擷取資訊。 您可以透過 Visual Studio 編輯資料表。
開啟 Visual Studio。
從功能表中,按兩下 [檢視>雲端總管]。
雲端總管會以固定專案的形式開啟(耐心,因為載入可能需要時間)。
注意
如果您用來建立記憶體 帳戶的訂用帳戶 看不到,請確定您有:
登入與您用於 Azure 入口網站的帳戶相同。
從 [帳戶管理] 頁面選取您的訂用帳戶(您可能需要從您的帳戶設定套用篩選):
您的 Azure 雲端服務將會顯示。 尋找 [記憶體帳戶 ],然後按兩下該帳戶左側的箭號,展開您的帳戶。
展開之後,您應該可以使用新建立的 記憶體帳戶 。 按兩下記憶體左側的箭號,然後展開之後,尋找 [資料表 ],然後按兩下該位置旁的箭號,以顯示 您在上一章中建立的數據表 。 按兩下您的 資料表。
您的數據表將會在 Visual Studio 視窗的中央開啟。 按兩下具有 [加號] 的數據表圖示 + 。
隨即會出現視窗,提示您新增 實體。 您將總共建立三個實體,每個實體都有數個屬性。 您會發現已提供 PartitionKey 和 RowKey,因為數據表會使用這些數據來尋找您的數據。
更新 PartitionKey 和 RowKey 的值,如下所示(請記得針對您新增的每個數據列屬性執行這項操作,但每次都會遞增 RowKey):
按兩下 [新增屬性 ] 以新增額外的數據列。 讓您的第一個空白數據表符合下表。
完成時,請按一下 [確定]。
警告
確定您已將 X、Y 和 Z 的類型變更為 Double。
您現在會注意到您的資料表有一列數據。 + 再次按兩下 [加號] 圖示以新增另一個實體。
建立其他屬性,然後設定新實體的值以符合如下所示的值。
重複最後一個步驟以新增另一個實體。 將此實體的值設定為如下所示的值。
您的數據表現在看起來應該像下面這樣。
您已完成本章。 請務必儲存。
第 6 章 - 建立 Azure 函式應用程式
建立 Azure 函式應用程式,此應用程式將由傳統型應用程式呼叫以更新 資料表 服務,並透過通知中 樞傳送通知。
首先,您需要建立一個檔案,以允許 Azure 函式載入您需要的連結庫。
開啟 [記事本 ] (按 Windows 鍵並輸入記事本)。
在 [記事本] 開啟時,將下面的 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 入口網站。
登入之後,按兩下左上角的 [ 新增 ],然後搜尋 [函式應用程式],然後按 Enter。
注意
[新增] 一詞可能已取代為在較新的入口網站中建立資源。
新頁面將提供函式 App Service 的描述。 在此提示的左下角,選取 [ 建立] 按鈕,以建立與這項服務的關聯。
按兩下 [建立] 之後,請填入下列內容:
針對 [ 應用程式名稱],插入此服務實例所需的名稱。
選取 [訂用帳戶]。
選取適合您的定價層,如果這是第一次建立 函式 App Service,您應該可以使用免費層。
選擇資源群組或建立新的群組。 資源群組提供一種方式來監視、控制存取、布建和管理 Azure 資產集合的計費。 建議將所有與單一專案相關聯的 Azure 服務(例如,例如這些實驗室)保留在通用資源群組之下。
如果您想要深入瞭解 Azure 資源群組,請遵循此 連結以瞭解如何管理資源群組。
針對 OS,按兩下 [Windows],就如同預期平臺一樣。
選取主 控方案 (本教學課程使用取用 方案。
選取 [位置] (選擇與您在上一個步驟中建置的記憶體相同的位置)
針對 [記憶體] 區段,您必須選取您在上一個步驟中建立的記憶體服務。
您不需要此應用程式中的 Application Insights,因此請放心將其關閉。
按一下 [建立]。
按兩下 [ 建立 ] 之後,您必須等候服務建立,這可能需要一分鐘的時間。
建立服務實例之後,入口網站中就會顯示通知。
按兩下通知以探索新的服務實例。
按兩下通知中的 [ 移至資源 ] 按鈕,以探索新的服務實例。
點選 「函式」 旁的 + [加號] 圖示, 以建立新的 。
在中央面板中, [函式 建立] 視窗隨即出現。 忽略面板上半部的信息,然後按兩下位於 底部附近的 [自定義函式] (在藍色區域中,如下所示)。
視窗中的新頁面會顯示各種函式類型。 向下卷動以檢視紫色類型,然後按兩下 [ HTTP PUT ] 元素。
重要
不過,您可能必須進一步向下卷動頁面(如果已進行 Azure 入口網站更新,此影像可能看起來可能不完全相同),不過,您正在尋找名為 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; } }
注意
使用包含的連結庫,函式會接收在 Unity 場景中移動的物件名稱和位置(稱為 UnityGameObject 的 C# 物件)。 接著,此物件會用來更新所建立數據表內的物件參數。 在此之後,函式會呼叫您建立的通知中樞服務,以通知所有已訂閱的應用程式。
在程式代碼就緒后,按兩下 [ 儲存]。
接下來,按下 < 頁面右側的 [箭號] 圖示。
面板會從右側滑入。 在該面板中,按兩下 [上傳],[檔案瀏覽器] 隨即出現。
流覽至先前在 [記事本] 中建立的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 數據表記憶體][數據表]。
請確定下列專案與您的資訊相符,因為它們可能不同(下列步驟下方有影像):
數據表名稱:您在 Azure 儲存體 數據表服務內建立的數據表名稱。
記憶體帳戶連線: 單擊 [新增],其會出現在下拉功能表旁,而面板會出現在窗口右側。
選取您 先前建立的記憶體帳戶來裝載 函式應用程式。
您會發現已建立記憶體 帳戶 連線值。
完成之後,請務必按 [ 儲存 ]。
[ 輸入] 頁面現在應該符合下列內容,其中顯示 您的資訊 。
接下來,按兩下 [Azure 通知中樞][通知] - 在 [輸出] 底下。 請確定下列專案符合 您的 資訊,因為它們可能不同(下列步驟下方有影像):
通知中樞名稱:這是您先前建立的 通知中樞 服務實例名稱。
通知中樞命名空間連線:單擊 [新增],其會出現在下拉功能表旁。
[連線] 彈出視窗隨即出現(見下圖),您需要選取您先前設定的通知中樞命名空間。
從中間下拉功能表中選取您的 通知中樞 名稱。
將 [原則] 下拉功能表設定為 DefaultFullSharedAccessSignature。
按兩下 [ 選取] 按鈕返回。
[輸出] 頁面現在應該符合下列內容,但改為與您的資訊相符。 請務必按 [ 儲存]。
警告
請勿直接編輯通知中樞名稱(這應該全部都使用 進階編輯器 來完成,前提是您已正確遵循先前的步驟。
此時,您應該測試函式,以確保函式正常運作。 若要這樣做:
再次瀏覽至函式頁面:
回到函式頁面,按兩下 頁面最右邊的 [測試 ] 索引標籤,以開啟 [ 測試 ] 刀鋒視窗:
在 刀鋒視窗的 [要求本文 ] 文字框中,貼上下列程式代碼:
{ "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 和混合實境進行開發的一般設定,因此是其他專案的良好範本。
設定及測試混合實境沉浸式頭戴式裝置。
注意
本課程不需要運動控制器。 如果您需要設定沉浸式頭戴式裝置的支援,請遵循此 連結以瞭解如何設定 Windows Mixed Reality。
開啟 Unity ,然後按兩下 [ 新增]。
您需要提供 Unity 項目名稱,插入 UnityDesktopNotifHub。 請確定專案類型已設定為 3D。 將 [ 位置 ] 設定為您適當的位置(請記住,更接近根目錄會更好)。 然後按兩下 [ 建立專案]。
在 Unity 開啟時,值得檢查預設 的腳本編輯器 設定為 Visual Studio。 移至 [ 編輯>喜好設定 ],然後從新視窗流覽至 [外部工具]。 將外部腳本編輯器變更為 Visual Studio 2017。 關閉 [喜好設定] 視窗。
接下來,移至 [檔案>建置設定] 並選取 [通用 Windows 平台],然後按兩下 [切換平臺] 按鈕以套用您的選取專案。
在 [檔案>建置設定] 中,請確定:
目標裝置 設定為 [任何裝置]
此應用程式適用於您的桌面,因此必須是 任何裝置
組建類型 設定為 D3D
SDK 設定為 [最新安裝]
Visual Studio 版本 設定為 [最新安裝]
[建置並執行 ] 設定為 [ 本機計算機]
在這裡,值得儲存場景,並將它新增至組建。
選取 [ 新增開啟場景] 來執行此動作。 隨即會出現儲存視窗。
為此建立新的資料夾,以及任何未來場景,然後選取 [新增資料夾] 按鈕,以建立新的資料夾 ,並將它命名為 Scenes。
開啟新建立 的 Scenes 資料夾,然後在 [檔名: ] 字段中輸入 NH_Desktop_Scene,然後按 [ 儲存]。
[建置設定] 中的其餘設定現在應該保留為預設值。
在相同的視窗中,按兩下 [播放程式設定] 按鈕,這會在 Inspector 所在的空間中開啟相關的面板。
在此面板中,需要驗證一些設定:
在 [ 其他設定] 索引標籤中:
文稿運行時間版本 應該是 實驗性版本 (.NET 4.6 對等專案)
腳本後端 應該是 .NET
API 相容性層級 應該是 .NET 4.6
在 [發佈設定] 索引標籤的 [功能] 底下,檢查:
InternetClient
回到 [組建設定] Unity C# 專案不再呈現灰色;勾選此旁邊的複選框。
關閉 [建置設定] 視窗。
儲存場景和專案檔>儲存場景/檔案>儲存專案。
重要
如果您想要略過 此專案的 Unity 設定 元件(傳統型應用程式),並繼續直接進入程式代碼,請隨意 下載此 .unitypackage、將它匯入至您的專案做為 自定義套件,然後從 第 9 章繼續進行。 您仍然需要新增文稿元件。
第 8 章 - 在 Unity 中匯入 DLL
您將使用適用於 Unity 的 Azure 儲存體 (其本身會利用適用於 Azure 的 .Net SDK)。 如需詳細資訊,請遵循此連結,以瞭解適用於 Unity 的 Azure 儲存體。
Unity 中目前有已知問題,需要在匯入之後重新設定外掛程式。 這些步驟(本節中的 4 - 7)在 Bug 解決之後將不再需要。
若要將 SDK 匯入您自己的專案,請確定您已從 GitHub 下載最新的 .unitypackage。 然後執行下列動作:
使用 [資產>匯入套件自定義套件>] 功能表選項,將 .unitypackage 新增至 Unity。
在快顯的 [匯入 Unity 套件] 方塊中,您可以選取 [外掛程式>記憶體] 底下的所有專案。 取消核取其他所有專案,因為本課程不需要。
按兩下 [ 匯 入] 按鈕,將專案新增至您的專案。
移至 [專案] 檢視中 [外掛程式] 底下的 [記憶體] 資料夾,並只選取下列外掛程式:
- Microsoft.Data.Edm
- Microsoft.Data.OData
- Microsoft.WindowsAzure.Storage
- Newtonsoft.Json
- System.Spatial
選取這些特定外掛程式后,取消核取 [任何平臺],然後取消核取 [WSAPlayer],然後按兩下 [套用]。
注意
我們會將這些特定外掛程式標示為只能在 Unity 編輯器中使用。 這是因為 WSA 資料夾中有不同版本的相同外掛程式,將在專案從 Unity 匯出之後使用。
在 [ 記憶體 外掛程式] 資料夾中,只選取:
Microsoft.Data.Services.Client
核取 [平台設定] 底下的 [不要處理] 方塊,然後按兩下 [套用]。
注意
我們正在標記此外掛程式「不要處理」,因為 Unity 元件修補程式處理此外掛程式時發生困難。 即使未處理外掛程式,外掛程式仍可運作。
第 9 章 - 在 Desktop Unity 專案中建立 TableToScene 類別
您現在必須建立包含執行此應用程式之程式代碼的腳稿。
您需要建立的第一個腳本是 TableToScene,負責:
- 讀取 Azure 數據表內的實體。
- 使用 Table 數據,判斷要繁衍的物件,以及哪個位置。
您需要建立的第二個腳本是 CloudScene,負責:
- 註冊左鍵事件,讓用戶在場景周圍拖曳物件。
- 從這個 Unity 場景串行化對象數據,並將其傳送至 Azure 函式應用程式。
若要建立此類別:
以滑鼠右鍵按兩下 [資產資料夾] 位於 [項目面板] 的 [建立>資料夾]。 將資料夾 命名為文稿。
按兩下剛建立的資料夾,以開啟它。
在 [腳本] 資料夾內按下滑鼠右鍵,按兩下 [建立>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 -- ";
注意
以您的 Azure 儲存體 Service 名稱和 accountKey 值取代 accountName 值,取代為 Azure 入口網站中 Azure 儲存體 服務中找到的金鑰值(請參閱下圖下方)。
現在新增 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 編輯器之前先儲存 。
從 [階層] 面板按兩下 [主要相機],使其屬性出現在 Inspector 中。
開啟 [ 腳本] 資料夾后,選取腳本 TableToScene 檔案 ,然後將它拖曳到 主相機。 結果應該如下所示:
第 10 章 - 在 Desktop Unity 專案中建立 CloudScene 類別
您需要建立的第二個腳本是 CloudScene,負責:
註冊左鍵事件,讓用戶在場景周圍拖曳物件。
從這個 Unity 場景串行化對象數據,並將其傳送至 Azure 函式應用程式。
若要建立第二個腳本:
以滑鼠右鍵按兩下 [腳稿] 資料夾內的 [建立],按兩下 [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;
將 azureFunctionEndpoint 值取代為 Azure Function App Service 中 Azure Function App Service 中找到的 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 Service,這會更新 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 腳本拖曳至 主相機。
從 [階層] 面板按兩下 [主要相機],使其屬性出現在 Inspector 中。
開啟 [ 腳本] 資料夾后,選取 CloudScene 腳本,然後將它拖曳到 主相機。 結果應該如下所示:
第 11 章 - 將傳統型專案建置至 UWP
此專案的 Unity 區段所需的所有項目現在都已完成。
流覽至 [建置設定] (檔案>建置設定)。
從 [ 建置設定] 視窗中,按兩下 [ 建置]。
[檔案總管] 視窗隨即出現,提示您輸入 [建置] 的位置。 建立新資料夾(按兩下 左上角的[新增資料夾 ],並將它命名為 BUILDS。
開啟新的 BUILDS 資料夾,然後建立另一個資料夾(再次使用新資料夾),並將它命名為NH_Desktop_App。
選取 NH_Desktop_App 。 按兩下 [ 選取資料夾]。 專案需要一分鐘左右的時間才能建置。
建置之後,檔案總管 會顯示新專案的位置。 不過,您不需要開啟它,因為您需要先在接下來的幾章中建立其他 Unity 專案。
第 12 章 - 設定混合實境 Unity 專案
以下是使用混合實境進行開發的典型設定,因此是其他專案的良好範本。
開啟 Unity ,然後按兩下 [ 新增]。
您現在必須提供 Unity 項目名稱,插入 UnityMRNotifHub。 請確定專案類型已設定為 3D。 將 [ 位置 ] 設定為您適當的位置(請記住,更接近根目錄會更好)。 然後按兩下 [ 建立專案]。
在 Unity 開啟時,值得檢查預設 的腳本編輯器 設定為 Visual Studio。 移至 [ 編輯>喜好設定 ],然後從新視窗流覽至 [外部工具]。 將外部腳本編輯器變更為 Visual Studio 2017。 關閉 [喜好設定] 視窗。
接下來,移至 [檔案>建置設定],然後按兩下 [切換平臺] 按鈕,將平臺切換為 通用 Windows 平台。
移至 [ 檔案>建置設定 ],並確定:
目標裝置 設定為 [任何裝置]
針對 Microsoft HoloLens,將 [目標裝置] 設定為 [HoloLens]。
組建類型 設定為 D3D
SDK 設定為 [最新安裝]
Visual Studio 版本 設定為 [最新安裝]
[建置並執行 ] 設定為 [ 本機計算機]
在這裡,值得儲存場景,並將它新增至組建。
選取 [ 新增開啟場景] 來執行此動作。 隨即會出現儲存視窗。
為此建立新的資料夾,以及任何未來場景,然後選取 [新增資料夾] 按鈕,以建立新的資料夾 ,並將它命名為 Scenes。
開啟新建立 的 Scenes 資料夾,然後在 [檔名: ] 字段中輸入 NH_MR_Scene,然後按 [ 儲存]。
[建置設定] 中的其餘設定現在應該保留為預設值。
在相同的視窗中,按兩下 [播放程式設定] 按鈕,這會在 Inspector 所在的空間中開啟相關的面板。
在此面板中,需要驗證一些設定:
在 [ 其他設定] 索引標籤中:
文稿運行時間版本 應該是 實驗性 版本 (.NET 4.6 對等專案)
腳本後端 應該是 .NET
API 相容性層級 應該是 .NET 4.6
在面板的進一步下,在 [XR 設定] 中,勾選 [支援虛擬實境] 中的 [XR 設定],確定已新增 Windows Mixed Reality SDK
在 [發佈設定] 索引標籤的 [功能] 底下,檢查:
InternetClient
回到 [建置設定] 中,Unity C# 專案不再呈現灰色:勾選此旁邊的複選框。
完成這些變更之後,請關閉 [建置設定] 視窗。
儲存場景和專案檔>儲存場景/檔案>儲存專案。
重要
如果您想要略過 此專案的 Unity 設定 元件(混合實境應用程式),並繼續直接進入程式代碼,請隨意 下載此 .unitypackage,將它匯入您的專案作為 自定義套件,然後從 第 14 章繼續進行。 您仍然需要新增文稿元件。
第 13 章 - 在混合實境 Unity 專案中匯入 DLL
您將使用適用於 Unity 連結庫的 Azure 儲存體(其使用適用於 Azure 的 .Net SDK)。 請遵循此連結,瞭解如何搭配 Unity 使用 Azure 儲存體。 Unity 中目前有已知問題,需要在匯入之後重新設定外掛程式。 這些步驟(本節中的 4 - 7)在 Bug 解決之後將不再需要。
若要將 SDK 匯入您自己的專案,請確定您已下載最新的 .unitypackage。 然後執行下列動作:
使用 [資產>匯入套件自定義套件>] 功能表選項,將您從上述下載的 .unitypackage 新增至 Unity。
在快顯的 [匯入 Unity 套件] 方塊中,您可以選取 [外掛程式>記憶體] 底下的所有專案。
按兩下 [ 匯 入] 按鈕,將專案新增至您的專案。
移至 [專案] 檢視中 [外掛程式] 底下的 [記憶體] 資料夾,並只選取下列外掛程式:
- Microsoft.Data.Edm
- Microsoft.Data.OData
- Microsoft.WindowsAzure.Storage
- Newtonsoft.Json
- System.Spatial
選取這些特定外掛程式后,取消核取 [任何平臺],然後取消核取 [WSAPlayer],然後按兩下 [套用]。
注意
您要將這些特定外掛程式標示為只能在 Unity 編輯器中使用。 這是因為 WSA 資料夾中有不同版本的相同外掛程式,將在專案從 Unity 匯出之後使用。
在 [ 記憶體 外掛程式] 資料夾中,只選取:
Microsoft.Data.Services.Client
核取 [平台設定] 底下的 [不要處理] 方塊,然後按兩下 [套用]。
注意
您正在標記此外掛程式「不要處理」,因為 Unity 元件修補程式處理此外掛程式時發生困難。 即使未處理外掛程式,外掛程式仍可運作。
第 14 章 - 在混合實境 Unity 專案中建立 TableToScene 類別
TableToScene 類別與第 9 章中所述的類別相同。 遵循第 9 章中所述的相同程式,在混合實境 Unity 專案中建立相同的類別。
完成本章之後,您的 Unity 專案都會在主相機上設定此類別。
第 15 章 - 在混合實境 Unity 專案中建立 NotificationReceiver 類別
您需要建立的第二個腳本是 NotificationReceiver,負責:
- 在初始化時向通知中樞註冊應用程式。
- 接聽來自通知中樞的通知。
- 從收到的通知還原串行化對象數據。
- 根據還原串行化的數據,在場景中移動 GameObjects。
若要建立 NotificationReceiver 腳本:
以滑鼠右鍵按兩下 [腳稿] 資料夾內的 [建立],按兩下 [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 值,並以 Azure 入口網站中 [存取原則] 索引標籤中的 [Azure 通知中樞服務] 中找到的端點值取代 hubListenEndpoint 值(請參閱下圖)。
現在新增 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 方法,以允許應用程式從通知中樞連結庫接收通知,而不會與主線程發生衝突:
/// <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()會在初始化時向通知中樞服務註冊應用程式。 程式代碼會標記為 Unity 無法建置專案。 當您在 Visual Studio 中匯入 Azure Messaging 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 編輯器之前儲存變更。
從 [階層] 面板按兩下 [主要相機],使其屬性出現在 Inspector 中。
開啟 [ 腳本] 資料夾后,選取 NotificationReceiver 腳本,並將它拖曳到 主相機。 結果應該如下所示:
注意
如果您要針對 Microsoft HoloLens 進行此開發,則必須更新主相機的相機元件,以便:
- 清除旗標:純色
- 背景:黑色
第 16 章 - 將混合實境專案建置至 UWP
本章與上一個專案的建置程式相同。 此專案的 Unity 區段已全部完成,因此是時候從 Unity 建置它了。
流覽至 [建置設定] (檔案建置>設定 )。
從 [ 建置設定 ] 功能表中,確定 已勾選 Unity C# 專案*(這可讓您在建置之後編輯此專案中的腳本)。
完成之後,按兩下 [ 建置]。
[檔案總管] 視窗隨即出現,提示您輸入 [建置] 的位置。 建立新資料夾(按兩下 左上角的[新增資料夾 ],並將它命名為 BUILDS。
開啟新的 BUILDS 資料夾,然後建立另一個資料夾(再次使用新資料夾),並將它命名為NH_MR_App。
選取 NH_MR_App 。 按兩下 [ 選取資料夾]。 專案需要一分鐘左右的時間才能建置。
建置之後,會在新專案的位置開啟 檔案總管 視窗。
第 17 章 - 將 NuGet 套件新增至 UnityMRNotifHub 解決方案
警告
請記住,一旦您新增下列 NuGet 套件(並在下一 章中取消批注程式代碼),在 Unity 專案內重新開啟程式碼時,程式代碼就會顯示錯誤。 如果您想要返回 Unity 編輯器並繼續編輯,您需要批注該不穩定的程式代碼,稍後再取消批注,一旦您回到 Visual Studio。
混合實境建置完成後,流覽至您建置的混合實境專案,然後按兩下該資料夾中的方案 (.sln) 檔案,以使用Visual Studio 2017 開啟您的方案。 您現在必須新增 WindowsAzure.Messaging.managed NuGet 套件;這是用來從通知中樞接收通知的連結庫。
若要匯入 NuGet 套件:
在 方案總管 中,以滑鼠右鍵按下您的解決方案
按兩下 [ 管理 NuGet 套件]。
選取 [ 流覽] 索引標籤,然後搜尋 WindowsAzure.Messaging.managed。
選取結果(如下所示),然後在右側的視窗中,選取 [專案] 旁的複選框。 這會在 Project 旁的複選框中加上刻度,以及 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 章 - 將混合實境專案關聯至市集應用程式
您現在必須將混合實境專案與您在實驗室開始時建立的市集應用程式產生關聯。
開啟解決方案。
以滑鼠右鍵按兩下 [方案總管] 面板中的 [UWP 應用程式專案]、移至 [市集] 和 [將應用程式與市集建立關聯...]。
新的視窗隨即出現,稱為 將您的應用程式與 Windows 市集建立關聯。 按一下 [下一步] 。
它會載入與您登入之帳戶相關聯的所有應用程式。 如果您未登入您的帳戶,您可以在 此頁面登入 。
尋找您在本教學課程開頭建立的市集應用程式名稱,並加以選取。 然後按一下 [下一步]。
按一下 [關聯]。
您的應用程式現在 已與市集應用程式建立關聯 。 這是啟用通知的必要專案。
第 20 章 - 部署 UnityMRNotifHub 和 UnityDesktopNotifHub 應用程式
本章可能更容易與兩個人,因為結果將包含兩個應用程式執行,一個在您的電腦桌面上執行,另一個在沉浸式頭戴式裝置內執行。
沉浸式頭戴式裝置應用程式正在等候接收場景的變更(本機 GameObjects 的位置變更),而桌面應用程式將會變更其本機場景(位置變更),這會共用至 MR 應用程式。 先部署 MR 應用程式,後面接著桌面應用程式,讓接收者可以開始接聽,這很合理。
若要在本機 電腦上部署 UnityMRNotifHub 應用程式:
在 Visual Studio 2017 中開啟 UnityMRNotifHub 應用程式的解決方案檔案。
在 [解決方案平臺] 中,選取 [x86] [本機計算機]。
在 [解決方案組態] 中,選取 [偵錯]。
移至 [ 建置] 功能表 ,然後按下 [ 部署方案 ] 將應用程式側載至您的電腦。
您的應用程式現在應該會出現在已安裝的應用程式清單中,準備好啟動。
若要在本機 電腦上部署 UnityDesktopNotifHub 應用程式:
在 Visual Studio 2017 中開啟 UnityDesktopNotifHub 應用程式的解決方案檔案。
在 [解決方案平臺] 中,選取 [x86] [本機計算機]。
在 [解決方案組態] 中,選取 [偵錯]。
移至 [ 建置] 功能表 ,然後按下 [ 部署方案 ] 將應用程式側載至您的電腦。
您的應用程式現在應該會出現在已安裝的應用程式清單中,準備好啟動。
啟動混合實境應用程式,後面接著傳統型應用程式。
執行這兩個應用程式時,在桌面場景中移動物件(使用滑鼠左鍵)。 這些位置變更將會在本機進行、串行化,並傳送至函式 App Service。 函式 App Service 接著會更新數據表以及通知中樞。 收到更新之後,通知中樞會將更新的數據直接傳送至所有已註冊的應用程式(在此案例中為沉浸式頭戴式裝置應用程式),然後還原串行化傳入數據,並將新的位置數據套用至本機物件,並在場景中移動它們。
您已完成 Azure 通知中樞應用程式
恭喜,您建置了混合實境應用程式,利用 Azure 通知中樞服務並允許應用程式之間的通訊。
額外練習
練習 1
您是否可以瞭解如何變更 GameObjects 的色彩,並將該通知傳送給檢視場景的其他應用程式?
練習 2
您可以將 GameObjects 的移動新增至 MR 應用程式,並在傳統型應用程式中查看更新的場景嗎?