HoloLens (第 1 代) 和 Azure 308:跨裝置通知


注意

混合實境學院教學課程的設計是以 HoloLens (第 1 代) 和混合實境沉浸式頭戴裝置為準。 因此,對於仍在尋找這些裝置開發指引的開發人員而言,我們覺得這些教學課程很重要。 這些教學課程不會使用用於 HoloLens 2 的最新工具組或互動進行更新。 系統會保留這些資訊,以繼續在支援的裝置上運作。 未來將會張貼一系列新的教學課程,示範如何針對HoloLens 2進行開發。 此通知會在張貼時更新這些教學課程的連結。


最終產品 -start

在此課程中,您將瞭解如何使用 Azure 通知中樞、Azure 資料表和Azure Functions,將通知中樞功能新增至混合實境應用程式。

Azure 通知中樞 是一項 Microsoft 服務,可讓開發人員將目標和個人化的推播通知傳送至雲端內所有平臺。 這可以有效地讓開發人員與終端使用者通訊,或甚至根據案例在各種應用程式之間進行通訊。 如需詳細資訊,請流覽 Azure 通知中樞頁面

Azure Functions是 Microsoft 服務,可讓開發人員在 Azure 中執行小型程式碼片段'functions'。 這提供將工作委派給雲端的方式,而不是您的本機應用程式,這有許多優點。 Azure Functions支援數種開發語言,包括 C#、F#、Node.js、JAVA 和 PHP。 如需詳細資訊,請流覽Azure Functionspage

Azure 資料表 是 Microsoft 雲端服務,可讓開發人員將結構化非 SQL 資料儲存在雲端中,使其可在任何地方輕鬆存取。 此服務會支援無架構設計,可視需要演進資料表,因此非常有彈性。 如需詳細資訊,請流覽 Azure 資料表頁面

完成本課程之後,您將擁有混合實境沉浸式頭戴式裝置應用程式,以及桌上型電腦應用程式,這可以執行下列動作:

  1. 桌上型電腦應用程式可讓使用者使用滑鼠,在 2D 空間中移動物件 (X 和 Y) 。

  2. 電腦應用程式內的物件移動將會使用 JSON 傳送至雲端,其格式為字串,其中包含物件識別碼、類型和轉換資訊, (X 和 Y 座標) 。

  3. 混合實境應用程式與傳統型應用程式具有相同場景,將會從通知中樞服務收到有關物件移動的通知, (電腦應用程式剛更新) 。

  4. 收到包含物件識別碼、類型和轉換資訊的通知時,混合實境應用程式會將接收的資訊套用至自己的場景。

在您的應用程式中,您必須先瞭解如何將結果與您的設計整合。 本課程旨在教導您如何整合 Azure 服務與您的 Unity 專案。 您的工作是使用此課程取得的知識來增強混合實境應用程式。 本課程是獨立的教學課程,不會直接涉及任何其他Mixed Reality Labs。

裝置支援

課程 HoloLens 沉浸式頭戴裝置
MR 和 Azure 308:跨裝置通知 ✔️ ✔️

注意

雖然本課程主要著重于Windows Mixed Reality沉浸式 (VR) 頭戴式裝置,但您也可以將此課程中學到的內容套用至Microsoft HoloLens。 當您遵循本課程時,您會看到可能需要採用以支援 HoloLens 的任何變更注意事項。 使用 HoloLens 時,您可能會在語音擷取期間注意到一些回應。

必要條件

注意

本教學課程專為具備 Unity 和 C# 基本體驗的開發人員所設計。 另請注意,本檔中的必要條件和書面指示代表在撰寫 (2018 年 5 月) 時已測試及驗證的內容。 您可以隨意使用最新的軟體,如 安裝工具 一文中所列,但不應該假設本課程中的資訊會完全符合您在較新軟體中找到的內容,而不是下面所列的內容。

針對本課程,我們建議使用下列硬體和軟體:

在您開始使用 Intune 之前

  • 若要避免建置此專案時發生問題,強烈建議您在根資料夾或近根資料夾中建立本教學課程中提及的專案, (長資料夾路徑可能會導致建置時間) 的問題。
  • 您必須是 Microsoft 開發人員入口網站和應用程式註冊入口網站的擁有者,否則您將沒有在 第 2 章中存取應用程式的許可權。

第 1 章 - 在 Microsoft 開發人員入口網站上建立應用程式

若要使用 Azure 通知 中樞服務,您必須在 Microsoft 開發人員入口網站上建立應用程式,因為您的應用程式必須註冊,以便傳送和接收通知。

  1. 登入 Microsoft 開發人員入口網站

    您必須登入您的 Microsoft 帳戶。

  2. 從 [儀表板] 中,按一下 [建立新的應用程式]。

    建立應用程式

  3. 隨即會出現快顯視窗,其中您需要保留新應用程式的名稱。 在文字方塊中,插入適當的名稱;如果所選的名稱可用,則文字方塊右側會出現刻度。 插入可用的名稱之後,請按一下快顯左下方的 [保留產品名稱 ] 按鈕。

    反向名稱

  4. 現在建立應用程式之後,您就可以移至下一章。

第 2 章 - 擷取新的應用程式認證

登入應用程式註冊入口網站,其中會列出您的新應用程式,並擷取認證,以用來在Azure入口網站中設定通知中樞服務

  1. 流覽至 應用程式註冊入口網站

    應用程式註冊入口網站

    警告

    您必須使用您的 Microsoft 帳戶登入。
    必須是 您在上 一章中使用的 Microsoft 帳戶,以及 Windows 市集開發人員入口網站。

  2. 您會在 [ 我的應用程式 ] 區段下找到您的應用程式。 找到它之後,按一下它,您就會進入新的頁面,其中包含應用程式名稱加上 [註冊]。

    您新註冊的應用程式

  3. 向下捲動註冊頁面,以尋找您的應用程式 的應用程式秘密 區段和 套件 SID 。 複製這兩者以搭配下一章設定 Azure 通知中樞服務 使用。

    應用程式秘密

第 3 章 - 設定 Azure 入口網站:建立通知中樞服務

擷取您的應用程式認證後,您必須移至 Azure 入口網站,您將在其中建立 Azure 通知中樞服務。

  1. 登入 Azure 入口網站

    注意

    如果您還沒有 Azure 帳戶,則必須建立一個帳戶。 如果您在教室或實驗室案例中遵循本教學課程,請詢問講師或其中一個專業人員,以協助設定新的帳戶。

  2. 登入之後,按一下左上角的 [ 新增 ],然後搜尋 [通知中樞],然後按一下 [輸入]。

    搜尋通知中樞

    注意

    New一詞可能已取代為在較新的入口網站中建立資源

  3. 新頁面將提供 通知中樞 服務的描述。 在此提示的左下方,選取 [ 建立 ] 按鈕,以建立與此服務的關聯。

    建立通知中樞實例

  4. 按一下 [ 建立] 之後:

    1. 插入此服務實例所需的名稱。

    2. 提供 命名空間 ,您將能夠與此應用程式產生關聯。

    3. 選取 [位置]。

    4. 選擇 資源群組 或建立新的群組。 資源群組提供一種方式來監視、控制存取、布建和管理 Azure 資產集合的計費。 建議您保留與單一專案相關聯的所有 Azure 服務 (例如,這些實驗室) 在通用資源群組底下) 。

      如果您想要深入瞭解 Azure 資源群組,請遵循此 連結以瞭解如何管理資源群組

    5. 選取適當的 訂用帳戶

    6. 您也必須確認您已瞭解套用至此服務的條款及條件。

    7. 選取 [建立] 。

      填入服務詳細資料

  5. 按一下 [ 建立] 之後,您必須等候服務建立,這可能需要一分鐘的時間。

  6. 建立服務實例之後,入口網站中會出現通知。

    通知

  7. 按一下通知中的 [ 移至資源] 按鈕,以探索新的服務實例。 系統會帶您前往新的 通知中樞 服務實例。

    顯示通知視窗中醒目提示 [移至資源] 按鈕的螢幕擷取畫面。

  8. 在概觀頁面中,按一下頁面的一半,按一下 [Windows (WNS) ]。 右側的面板會變更以顯示兩個文字欄位,這需要您先前設定的應用程式中的 套件 SID 和安全性 金鑰

    新建立的中樞服務

  9. 將詳細資料複製到正確的欄位之後,請按一下 [ 儲存],並在通知中樞成功更新時收到通知。

    複製安全性詳細資料

第 4 章 - 設定 Azure 入口網站:建立資料表服務

建立通知中樞服務實例之後,請流覽回您的 Azure 入口網站,您可以在其中建立儲存體資源來建立 Azure 資料表服務。

  1. 如果尚未登入,請登入 Azure 入口網站

  2. 登入之後,按一下左上角的 [ 新增 ],然後搜尋 儲存體帳戶,然後按一下 Enter

    注意

    New一詞可能已取代為在較新的入口網站中建立資源

  3. 從清單中選取 [儲存體帳戶 - Blob、檔案、資料表、佇列 ]。

    搜尋儲存體帳戶

  4. 新的頁面將提供 儲存體帳戶 服務的描述。 在此提示的左下角,選取 [ 建立 ] 按鈕,以建立此服務的實例。

    建立儲存體實例

  5. 按一下 [ 建立] 之後,會出現面板:

    1. 插入此服務實例所需的 Name (必須是小寫) 。

    2. 針對 [部署模型],按一下 [資源管理員]。

    3. 針對 [帳戶種類],使用下拉式功能表,選取 [ 儲存體] (一般用途 v1)

    4. 選取適當的 位置

    5. 針對 [ 複寫] 下拉式功能表,選取 [ 讀取權限-異地備援儲存體] (RA-GRS)

    6. 針對 [效能],按一下 [ 標準]。

    7. [需要安全傳輸] 區段中,選取 [已停用]。

    8. 從 [ 訂用帳戶 ] 下拉式功能表中,選取適當的訂用帳戶。

    9. 選擇 資源群組 或建立新的群組。 資源群組提供一種方式來監視、控制存取、布建和管理 Azure 資產集合的計費。 建議您保留與單一專案相關聯的所有 Azure 服務 (例如,這些實驗室) 在通用資源群組底下) 。

      如果您想要深入瞭解 Azure 資源群組,請遵循此 連結以瞭解如何管理資源群組

    10. 如果這是選項,請將 [虛擬網路 ] 保留為 [已停用 ]。

    11. 按一下 [建立]。

      填入儲存體詳細資料

  6. 按一下 [ 建立] 之後,您必須等候服務建立,這可能需要一分鐘的時間。

  7. 建立服務實例之後,入口網站中會出現通知。 按一下通知以探索新的服務實例。

    新的儲存體通知

  8. 按一下通知中的 [ 移至資源] 按鈕,以探索新的服務實例。 系統會帶您前往新的儲存體服務實例概觀頁面。

    顯示 [部署成功] 視窗中醒目提示 [移至資源] 按鈕的螢幕擷取畫面。

  9. 從概觀頁面,按一下右側的 [ 資料表]。

    顯示選取 [資料表位置] 的螢幕擷取畫面。

  10. 右側的面板會變更以顯示 資料表服務 資訊,其中您需要新增資料表。 按一下左上角的 [ +資料表] 按鈕即可執行此動作。

    開啟資料表

  11. 將會顯示新的頁面,其中您需要輸入 資料表名稱。 這是您將在稍後的 Chapters 中參考應用程式中資料的名稱。 插入適當的名稱,然後按一下 [ 確定]。

    建立新的資料表

  12. 建立新的資料表之後,您就可以在底部的 [ 資料表服務 ] 頁面 (看到它) 。

    新資料表已建立

第 5 章 - 在 Visual Studio 中完成 Azure 資料表

現在已設定您的 資料表服務 儲存體帳戶,現在可以將資料加入其中,以便用來儲存和擷取資訊。 您可以透過 Visual Studio編輯資料表。

  1. 開啟 Visual Studio

  2. 從功能表中,按一下 [檢視>雲端總管]。

    開啟雲端總管

  3. Cloud Explorer會以停駐專案的形式開啟, (病患,因為載入可能需要時間) 。

    注意

    如果您用來建立 儲存體帳戶 的訂用帳戶看不到,請確定您有:

    • 登入與您用於 Azure 入口網站之帳戶相同的帳戶。

    • 從帳戶管理頁面選取您的訂用帳戶 (您可能需要從您的帳戶設定套用篩選) :

      尋找訂用帳戶

  4. 將會顯示您的 Azure 雲端服務。 尋找 [儲存體帳戶 ],然後按一下該帳戶左邊的箭號,以展開您的帳戶。

    開啟儲存體帳戶

  5. 展開之後,應該可以使用您新建立的 儲存體帳戶 。 按一下儲存體左側的箭號,然後在展開之後,尋找 [ 資料表 ],然後按一下該位置旁的箭號,以顯示您在上一章中建立的 資料表 。 按兩下您的 資料表

    開啟場景物件資料表

  6. 您的資料表將會在 Visual Studio 視窗的中心開啟。 按一下具有 (加上) 的資料表圖示 +

    新增資料表

  7. 隨即會出現一個視窗,提示您 新增實體。 您將總共建立三個實體,每個實體都有數個屬性。 您會發現已提供 PartitionKeyRowKey ,因為資料表會使用這些資料來尋找您的資料。

    資料分割和資料列索引鍵

  8. 更新PartitionKeyRowKey的值,如下所示 (請記得針對您新增的每個資料列屬性執行這項操作,但每次) 遞增 RowKey:

    新增正確的值

  9. 按一下 [新增屬性 ] 以新增額外的資料列。 讓您的第一個空白資料表符合下表。

  10. 完成時按一下 [ 確定 ]。

    完成時按一下 [確定]

    警告

    確定 您已將XYZ的類型變更為 Double

  11. 您會注意到資料表現在有一個資料列。 +再次按一下 (加) 圖示以新增另一個實體。

    第一列

  12. 建立其他屬性,然後設定新實體的值,以符合如下所示的值。

    新增 Cube

  13. 重複最後一個步驟以新增另一個實體。 將此實體的值設定為如下所示的值。

    新增圓柱圖

  14. 您的資料表現在看起來應該像下面這樣。

    資料表完成

  15. 您已完成本章。 請務必儲存。

第 6 章 - 建立 Azure 函式應用程式

建立 Azure 函式應用程式,由傳統型應用程式呼叫以更新 資料表 服務,並透過 通知中樞傳送通知

首先,您需要建立一個檔案,讓您的 Azure 函式能夠載入所需的程式庫。

  1. 開啟 [記事本 ] (按 Windows 鍵,然後輸入記事本) 。

    開啟記事本

  2. 在 [記事本] 開啟時,將下面的 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"
        }
        }
    }
    }
    
  3. 登入 Azure 入口網站

  4. 登入之後,按一下左上角的 [ 新增 ],然後搜尋 函數應用程式,然後按 Enter

    搜尋函式應用程式

    注意

    在較新的入口網站中, [新增 ] 這個字可能已取代為 建立資源

  5. 新頁面將提供 函式 App Service 的描述。 在此提示的左下角,選取 [ 建立 ] 按鈕,以建立與此服務的關聯。

    函式應用程式實例

  6. 按一下 [ 建立] 之後,請填寫下列內容:

    1. 針對 [應用程式名稱],插入此服務實例所需的名稱。

    2. 選取 [訂用帳戶] 。

    3. 選取適合您的定價層,如果這是第一次建立函式App Service,則免費層應該可供您使用。

    4. 選擇 資源群組 或建立新的群組。 資源群組提供一種方式來監視、控制存取、布建和管理 Azure 資產集合的計費。 建議將所有與單一專案相關聯的 Azure 服務保留 (例如,這些實驗室) 在通用資源群組) 下。

      如果您想要深入瞭解 Azure 資源群組,請遵循此 連結以瞭解如何管理資源群組

    5. 針對 [作業系統],按一下 [Windows],如同預期平臺一樣。

    6. (本教學 課程 使用取用方案,請選取主 控方案

    7. 選取 [位置 ] (選擇與您在上一個步驟中建置的儲存體相同的位置)

    8. 針對 [ 儲存體 ] 區段, 您必須選取您在上一個步驟中建立的儲存體服務

    9. 您不需要此應用程式中的 Application Insights ,因此請放心地將其 關閉

    10. 按一下 [建立]。

      建立新的實例

  7. 按一下 [ 建立 ] 之後,您必須等候服務建立,這可能需要一分鐘的時間。

  8. 建立服務實例之後,入口網站中會出現通知。

    新增通知

  9. 按一下通知以探索新的服務實例。

  10. 按一下通知中的 [ 移至資源 ] 按鈕,以探索新的服務實例。

    顯示 [部署成功] 的螢幕擷取畫面,其中已醒目提示 [移至資源] 按鈕。

  11. 按一下函 + 式旁的 (加上) 圖示,以建立新的

    新增函式

  12. 在中央面板中,[ 式建立] 視窗隨即出現。 忽略面板上半部的資訊,然後按一下 [ 自訂] 函式,其位於藍色區域中底部 (附近,如下所示) 。

    自訂函式

  13. 視窗中的新頁面會顯示各種函式類型。 向下捲動以檢視紫色類型,然後按一下 [HTTP PUT ] 元素。

    HTTP put 連結

    重要

    如果您已) Azure 入口網站更新,您可能必須向下捲動頁面 (,而且此映射看起來可能不完全相同,不過,您要尋找稱為 HTTP PUT的專案。

  14. HTTP PUT 視窗隨即出現,您需要在其中設定函式 (請參閱下方的影像) 。

    1. 針對 [語言], 使用下拉式功能表選取 [C#]。

    2. 針對 [名稱], 輸入適當的名稱。

    3. 在 [ 驗證層級 ] 下拉式功能表中,選取 [ 函式]。

    4. 針對 [ 資料表名稱 ] 區段,您必須使用您先前用來建立 資料表 服務的確切名稱, (包括相同的字母大小寫) 。

    5. 在 [ 儲存體帳戶連線 ] 區段中,使用下拉式功能表,然後從該處選取您的儲存體帳戶。 如果不存在,請按一下區段標題旁的 [ 新增 ] 超連結,以顯示另一個面板,其中應該列出您的儲存體帳戶。

      顯示 [儲存體帳戶連線] 區段的螢幕擷取畫面,其中已選取 [新增] 超連結。

  15. 按一下 [建立 ],您會收到已成功更新設定的通知。

    create 函式

  16. 按一下 [建立]之後,系統會將您重新導向至函式編輯器。

    更新函式程式碼

  17. 將下列程式碼插入函式編輯器中, (取代函式中的程式碼) :

    #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 場景中移動 (為 C# 物件,稱為 UnityGameObject) 。 然後,此物件會用來更新所建立資料表內的物件參數。 接著,函式會呼叫您建立的通知中樞服務,以通知所有已訂閱的應用程式。

  18. 就地執行程式碼後,按一下 [ 儲存]。

  19. 接下來,按一下 < 頁面右側 (箭號) 圖示。

    開啟上傳面板

  20. 面板會從右側滑入。 在該面板中,按一下 [ 上傳],[檔案瀏覽器] 隨即出現。

  21. 流覽至 ,然後按一下您先前在[記事本] 中建立的project.json檔案,然後按一下 [開啟] 按鈕。 此檔案會定義函式將使用的程式庫。

    上傳 json

  22. 檔案上傳後,它會出現在右側的面板中。 按一下它會在 函式 編輯器中開啟它。 其看起來必須與下一個影像 完全相同 , (步驟 23) 下方。

  23. 然後,在左側面板的 [函式] 下方,按一下 [ 整合 ] 連結。

    integrate 函式

  24. 在下一頁的右上角,按一下 [ 進階編輯器 ] (,如下所示) 。

    開啟進階編輯器

  25. 函式.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"
        }
    ]
    }
    
  26. 您的編輯器現在看起來應該像下圖:

    回到標準編輯器

  27. 您可能會注意到您剛才插入的輸入參數可能不符合您的資料表和儲存體詳細資料,因此必須以您的資訊進行更新。 請勿在此執行此動作,因為接下來會加以說明。 只要按一下頁面右上角的標準 編輯器 連結,即可返回。

  28. 回到標準編輯器,按一下 [輸入] 底下的 [Azure 資料表儲存體 (資料表) ]。

    資料表輸入

  29. 請確定下列 專案與您的資訊 相符,因為它們可能不同 (下圖) :

    1. 資料表名稱:您在 Azure 儲存體、資料表服務內建立的資料表名稱。

    2. 儲存體帳戶連線: 按一下 [新增],其會出現在下拉式功能表旁,而面板會出現在視窗右側。

      顯示 [儲存體帳戶] 視窗的螢幕擷取畫面,其中視窗右側的面板上已醒目提示 [新建]。

      1. 選取您先前建立的 儲存體帳戶來裝載 函式應用程式。

      2. 您會注意到已建立 儲存體帳戶 連線值。

      3. 完成之後,請務必按 [儲存 ]。

    3. [ 輸入] 頁面現在應該符合下列內容,其中顯示 您的資訊

      輸入完成

  30. 接下來,按一下 [輸出] 底下的[Azure 通知中樞] (通知) 。 請確定下列 專案與您的資訊 相符,因為它們可能不同, (下列步驟下方有影像) :

    1. 通知中樞名稱:這是您先前建立的 通知中樞 服務實例名稱。

    2. 通知中樞命名空間連線:按一下 [新增],其會出現在下拉式功能表旁。

      檢查輸出

    3. [連線] 快顯視窗會顯示 (下圖) ,您需要選取您先前設定的通知中樞命名空間

    4. 從中間下拉式功能表中選取您的 通知中樞 名稱。

    5. 將 [ 原則 ] 下拉式功能表設定為 DefaultFullSharedAccessSignature

    6. 按一下 [ 選取] 按鈕以返回。

      輸出更新

  31. [ 輸出] 頁面現在應該符合下列內容,但會改為 與您的 資訊相符。 請務必按 [儲存]。

警告

請勿直接編輯通知中樞名稱, (這應該全部都使用進階編輯器來完成,前提是您已正確遵循先前的步驟。

顯示 [輸出] 頁面的螢幕擷取畫面,其中包含一般資訊。

  1. 此時,您應該測試函式,以確保函式正常運作。 若要這樣做:

    1. 再次流覽至函式頁面:

      顯示函式頁面的螢幕擷取畫面,其中已醒目提示新建立的函式。

    2. 回到函式頁面,按一下頁面最右側的 [ 測試 ] 索引標籤,以開啟 [ 測試 ] 刀鋒視窗:

      函式頁面的螢幕擷取畫面,右側已醒目提示 [測試]。

    3. 在刀鋒視窗的 [ 要求本文] 文字方塊中,貼上下列程式碼:

      {  
          "Type":null,
          "X":3,
          "Y":0,
          "Z":1,
          "PartitionKey":null,
          "RowKey":"Obj2",
          "Timestamp":"0001-01-01T00:00:00+00:00",
          "ETag":null
      }
      
    4. 在測試程式碼就緒後,按一下右下角的 [ 執行 ] 按鈕,並執行測試。 測試的輸出記錄會出現在主控台區域中,您的函式程式碼下方。

      顯示主控台區域中測試輸出記錄的螢幕擷取畫面。

    警告

    如果上述測試失敗,您必須仔細檢查您是否確實遵循上述步驟,特別是 整合面板中的設定。

第 7 章 - 設定桌面 Unity 專案

重要

您目前正在建立的桌面應用程式 無法在 Unity 編輯器中運作。 它必須在編輯器外部執行,遵循建置應用程式,使用 Visual Studio (或已部署的應用程式) 。

以下是使用 Unity 和混合實境進行開發的一般設定,因此是其他專案的良好範本。

設定及測試混合實境沉浸式頭戴式裝置。

注意

不需要 此課程的動作控制器。 如果您需要設定沉浸式頭戴式裝置的支援,請遵循此連結來瞭解如何設定Windows Mixed Reality

  1. 開啟 Unity ,然後按一下 [ 新增]。

    [Unity 專案] 視窗的螢幕擷取畫面,其中右上方醒目提示 [新增] 專案圖示。

  2. 您需要提供 Unity 專案名稱,插入 UnityDesktopNotifHub。 請確定專案類型已設定為 3D。 將 [位置 ] 設定為適合您 (記住,較接近根目錄的較佳) 。 然後按一下 [ 建立專案]。

    建立專案

  3. 開啟 Unity 時,值得檢查預設 腳本編輯器 已設定為 Visual Studio。 移至[編輯>喜好設定],然後從新視窗流覽至[外部工具]。 將 外部腳本編輯器 變更為 Visual Studio 2017。 關閉 [喜好設定] 視窗。

    設定外部 VS 工具

  4. 接下來,移至 [檔案>建置設定] 並選取[通用 Windows 平臺],然後按一下 [切換平臺] 按鈕以套用您的選取專案。

    switch 平臺

  5. 在 [檔案>建置設定] 中,請確定:

    1. 目標裝置 已設定為 [任何裝置]

      此應用程式將適用于您的桌面,因此必須是 任何裝置

    2. 組建類型 設定為 D3D

    3. SDK 已設定為 [最新安裝]

    4. Visual Studio 版本 設定為 [最新安裝]

    5. [建置並執行 ] 設定為 [ 本機電腦]

    6. 在這裡,值得儲存場景,並將它新增至組建。

      1. 選取 [ 新增開啟場景]來執行此動作。 隨即會出現儲存視窗。

        顯示右上方醒目提示 [新增開啟場景] 的螢幕擷取畫面。

      2. 為此建立新的資料夾,以及任何未來的場景,然後選取 [ 新增資料夾 ] 按鈕,以建立新的資料夾,並將其命名為 Scenes

        此螢幕擷取畫面顯示以左上方醒目提示 [新增資料夾] 所建立的新 Scenes 資料夾。

      3. 開啟新建立的 Scenes 資料夾,然後在 [ 檔案名: 文字] 欄位中,輸入 NH_Desktop_Scene,然後按 [ 儲存]。

        new NH_Desktop_Scene

    7. 建置 設定中的其餘設定現在應該保留為預設值。

  6. 在相同的視窗中,按一下 [ 播放程式設定 ] 按鈕,這會在 Inspector 所在的空間中開啟相關的面板。

  7. 在此面板中,必須驗證一些設定:

    1. 在 [ 其他設定] 索引 標籤中:

      1. 腳本執行時間版本 應該是 實驗性 (.NET 4.6 對等)

      2. 腳本後端 應該是 .NET

      3. API 相容性層級 應該是 .NET 4.6

        4.6 net 版本

    2. 在 [ 發佈設定] 索引標籤的 [ 功能] 底下,檢查:

      • InternetClient

        顯示 [功能] 底下已選取 [InternetClient] 的螢幕擷取畫面。

  8. 回到 組建設定Unity C# 專案 不再呈現灰色;勾選此旁的核取方塊。

  9. 關閉 [組建設定] 視窗。

  10. 儲存場景和專案>儲存場景/檔案>儲存專案

    重要

    如果您想要略過此專案的 Unity 設定 元件, (傳統型應用程式) ,然後直接進入程式碼,請隨意 下載此 .unitypackage、將它匯入您的專案作為 自訂套件,然後從 第 9 章繼續進行。 您仍然需要新增腳本元件。

第 8 章 - 在 Unity 中匯入 DLL

您將使用適用于 Unity 的 Azure 儲存體 (,其本身會利用適用于 Azure 的 .Net SDK) 。 如需詳細資訊,請遵循此 連結以瞭解適用于 Unity 的 Azure 儲存體

Unity 中目前有已知問題,需要在匯入之後重新設定外掛程式。 本節中的這些步驟 (4 - 7,) 在 Bug 解決之後就不再需要這些步驟。

若要將 SDK 匯入您自己的專案,請確定您已從 GitHub 下載最新的 .unitypackage 。 然後執行下列動作:

  1. 使用 [資產 > 匯入套件自訂套件 >] 功能表選項,將.unitypackage新增至 Unity。

  2. 在快顯的 [匯入 Unity 套件] 方塊中,您可以選取[外掛程式>儲存體] 底下的所有專案。 取消核取所有其他專案,因為此課程不需要。

    匯入封裝

  3. 按一下 [ 匯入 ] 按鈕,將專案新增至您的專案。

  4. 移至 [專案] 檢視中[外掛程式] 底下的 [儲存體] 資料夾,並只選取下列外掛程式:

    • Microsoft.Data.Edm
    • Microsoft.Data.OData
    • Microsoft.WindowsAzure.Storage
    • Newtonsoft.Json
    • System.Spatial

取消核取 [任何平臺]

  1. 選取 這些特定外掛程式後取消核取[任何平臺 ],然後 取消核取[WSAPlayer ],然後按一下 [ 套用]。

    套用平臺 dll

    注意

    我們會將這些特定外掛程式標示為只在 Unity 編輯器中使用。 這是因為 WSA 資料夾中有不同版本的相同外掛程式,將在專案從 Unity 匯出之後使用。

  2. 在 [ 儲存體 外掛程式] 資料夾中,只選取:

    • Microsoft.Data.Services.Client

      set 不會處理 dll

  3. 核取 [平臺設定] 底下的[不要處理] 方塊,然後按一下 [套用]。

    不套用任何處理

    注意

    我們正在標示此外掛程式「不要處理」,因為 Unity 元件修補程式處理此外掛程式時發生困難。 即使未處理外掛程式,外掛程式仍可運作。

第 9 章 - 在 Desktop Unity 專案中建立 TableToScene 類別

您現在必須建立包含執行此應用程式之程式碼的腳本。

您需要建立的第一個腳本是 TableToScene,負責:

  • 讀取 Azure 資料表內的實體。
  • 使用資料表資料,判斷要繁衍的物件,以及哪個位置。

您需要建立的第二個腳本是 CloudScene,負責:

  • 註冊滑鼠左鍵事件,讓使用者在場景周圍拖曳物件。
  • 從這個 Unity 場景序列化物件資料,並將其傳送至 Azure 函式應用程式。

若要建立此類別:

  1. 以滑鼠右鍵按一下 [資產資料夾] 位於 [專案面板] 的 [建立>資料夾]。 將資料夾命名為 Scripts

    建立腳本資料夾

    建立腳本資料夾 2

  2. 按兩下剛才建立的資料夾,以開啟它。

  3. [腳本]資料夾內按一下滑鼠右鍵,按一下 [建立>C# 腳本]。 將腳本命名為 TableToScene

    顯示如何建立新 'TableToScene' 腳本的螢幕擷取畫面。TableToScene rename

  4. 按兩下腳本,在 Visual Studio 2017 中加以開啟。

  5. 新增下列命名空間:

    using Microsoft.WindowsAzure.Storage;
    using Microsoft.WindowsAzure.Storage.Auth;
    using Microsoft.WindowsAzure.Storage.Table;
    using UnityEngine;
    
  6. 在 類別中,插入下列變數:

        /// <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 -- ";
    

    注意

    accountName 值取代為您的 Azure 儲存體服務名稱和 accountKey 值,取代為 Azure 儲存體服務中找到的金鑰值,在 Azure 入口網站中 (請參閱下圖) 。

    擷取帳戶金鑰

  7. 現在新增 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();
        }
    
  8. 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);
        }
    
  9. 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; }
        }
    
  10. 請務必先 儲存 ,再返回 Unity 編輯器。

  11. 從 [階層] 面板按一下[主要相機],使其屬性會出現在Inspector中。

  12. 開啟 [腳本 ] 資料夾後,選取 腳本 TableToScene 檔案 ,然後將它拖曳到 主要相機。 結果應如下所示:

    將腳本新增至主要相機

第 10 章 - 在桌面 Unity 專案中建立 CloudScene 類別

您需要建立的第二個腳本是 CloudScene,負責:

  • 註冊滑鼠左鍵事件,讓使用者在場景周圍拖曳物件。

  • 從這個 Unity 場景序列化物件資料,並將其傳送至 Azure 函式應用程式。

若要建立第二個腳本:

  1. [腳本 ] 資料夾內按一下滑鼠右鍵,按一下 [ 建立]、 [C# 腳本]。 將腳本命名為 CloudScene

    顯示如何建立新 'CloudScene' 腳本的螢幕擷取畫面。重新命名 CloudScene

  2. 新增下列命名空間:

    using Newtonsoft.Json;
    using System.Collections;
    using System.Text;
    using System.Threading.Tasks;
    using UnityEngine;
    using UnityEngine.Networking;
    
  3. 插入下列變數:

        /// <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;
    
  4. azureFunctionEndpoint值取代為您在 Azure 函式App Service Azure 入口網站中找到的 Azure 函式應用程式 URL,如下圖所示:

    get 函式 URL

  5. 現在新增 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();
        }
    
  6. Update () 方法中,新增下列程式碼,以偵測滑鼠輸入和拖曳,進而在場景中移動 GameObjects。 如果使用者已拖放物件,它會將物件的名稱和座標傳遞至 UpdateCloudScene () 方法,這會呼叫 Azure 函式 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));
            }
        }
    
  7. 現在新增 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();
            }
        }
    
  8. 儲存程式碼並返回 Unity

  9. CloudScene 腳本拖曳至 主要相機

    1. 從 [階層] 面板按一下[主要相機],使其屬性會出現在Inspector中。

    2. 開啟 [ 腳本 ] 資料夾後,選取 CloudScene 腳本,然後將它拖曳到 主要相機。 結果應如下所示:

      將雲端腳本拖曳到主要相機

第 11 章 - 將桌面專案建置至 UWP

此專案的 Unity 區段所需的所有專案現在都已完成。

  1. 流覽至 [建置設定] ([檔案>置設定]) 。

  2. 從 [ 建置設定 ] 視窗中,按一下 [ 建置]。

    顯示 [建置設定] 視窗的螢幕擷取畫面,其中已選取 [通用 Windows 平臺] 和右下角醒目提示的 [建置] 按鈕。

  3. 檔案總管視窗隨即出現,提示您輸入要建置的位置。 按一下左上角的 [ 新增 資料夾]) ,並將其命名為 BUILDS,以建立新資料夾 (。

    組建的新資料夾

    1. 開啟新的 BUILDS 資料夾,然後再次) 使用 [新增 資料夾] 建立另一個資料夾 (,並將其命名 為NH_Desktop_App

      資料夾名稱NH_Desktop_App

    2. 選取 NH_Desktop_App 。 按一下 [選取資料夾]。 專案需要一分鐘的時間才能建置。

  4. 在建置之後,檔案總管會顯示新專案的位置。 不過,您不需要開啟它,因為您需要先在接下來的章節中建立其他 Unity 專案。

第 12 章 - 設定 Mixed Reality Unity 專案

以下是使用混合實境進行開發的一般設定,因此是其他專案的良好範本。

  1. 開啟 Unity ,然後按一下 [ 新增]。

    顯示 [Unity 專案] 視窗的螢幕擷取畫面,其中右上方醒目提示 [新增]。

  2. 您現在必須提供 Unity 專案名稱,插入 UnityMRNotifHub。 請確定專案類型已設定為 3D。 將 [位置 ] 設定為適合您 (記住,較接近根目錄的較佳) 。 然後按一下 [ 建立專案]。

    name UnityMRNotifHub

  3. 開啟 Unity 時,值得檢查預設 腳本編輯器 已設定為 Visual Studio。 移至[編輯>喜好設定],然後從新視窗流覽至[外部工具]。 將 外部腳本編輯器 變更為 Visual Studio 2017。 關閉 [喜好設定] 視窗。

    將外部編輯器設定為 VS

  4. 接下來,移至 [檔案>建置設定],然後按一下 [切換平臺] 按鈕,將平臺切換為通用 Windows 平臺

    將平臺切換至 UWP

  5. 移至[檔案>組建設定],並確定:

    1. 目標裝置 設定為 [任何裝置]

      針對Microsoft HoloLens,將[目標裝置] 設定為HoloLens

    2. 組建類型 設定為 D3D

    3. SDK 設定為 [最新安裝]

    4. Visual Studio 版本 設定為 [最新安裝]

    5. [建置並執行 ] 設定為 [本機電腦]

    6. 在這裡,值得儲存場景,並將它新增至組建。

      1. 選取 [ 新增開啟場景]來執行此動作。 隨即會出現儲存視窗。

        顯示 [建置設定] 視窗的螢幕擷取畫面,其中醒目提示右上方的 [新增開啟場景] 按鈕。

      2. 為此建立新的資料夾,以及任何未來的場景,然後選取 [ 新增資料夾 ] 按鈕,以建立新的資料夾,將它命名為 Scenes

        顯示 [儲存場景] 視窗左上方醒目提示 [新增資料夾] 的螢幕擷取畫面。

      3. 開啟新建立 的 Scenes 資料夾,然後在 [ 檔案名: 文字] 欄位中,輸入 NH_MR_Scene,然後按 [ 儲存]。

        新場景 - NH_MR_Scene

    7. 其餘設定在 [建置設定] 中,現在應該保留為預設值。

  6. 在相同的視窗中,按一下 [ 播放程式設定 ] 按鈕,這會在 偵測器 所在的空間中開啟相關的面板。

    開啟播放機設定

  7. 在此面板中,需要驗證一些設定:

    1. 在 [ 其他設定] 索引 標籤中:

      1. 腳本執行時間版本 應該是 實驗 性 (.NET 4.6 對等)

      2. 腳本後端應該是.NET

      3. API 相容性層級 應該是 .NET 4.6

        API 相容性

    2. 在面板下方,在[XR 設定] (中找到 [發佈設定) ],勾選[支援的虛擬實境],確定已新增Windows Mixed Reality SDK

      更新 xr 設定

    3. 在 [ 發佈設定] 索引標籤的 [ 功能] 底下,檢查:

      • InternetClient

        顯示已核取 InternetClient 之 [發佈設定] 索引標籤的螢幕擷取畫面。

  8. 回到 [組建設定], Unity C# 專案 不再呈現灰色:勾選此旁邊的核取方塊。

  9. 完成這些變更後,請關閉 [建置設定] 視窗。

  10. 儲存場景和專案>儲存場景/檔案>儲存專案

    重要

    如果您想要略過此專案的 Unity 設定 元件 (混合實境應用程式) ,並繼續直接進入程式碼,請隨意 下載此 .unitypackage、將其匯入您的專案作為 自訂套件,然後從 第 14 章繼續進行。 您仍然需要新增腳本元件。

第 13 章 - 匯入 Mixed Reality Unity 專案中的 DLL

您將使用適用于 Unity 的 Azure 儲存體程式庫 (,其使用適用于 Azure 的 .Net SDK) 。 請遵循此 連結,瞭解如何搭配 Unity 使用 Azure 儲存體。 Unity 中目前有已知問題,需要在匯入之後重新設定外掛程式。 本節中的這些步驟 (4 - 7,) 在 Bug 解決之後就不再需要。

若要將 SDK 匯入您自己的專案,請確定您已下載最新的 .unitypackage。 然後執行下列動作:

  1. 使用 [資產> 匯入套件自訂套件> ] 功能表選項,將您從上述下載的 .unitypackage 新增至 Unity。

  2. 在快顯的 [匯入 Unity 套件] 方塊中,您可以選取[外掛程式>儲存體] 底下的所有專案。

    匯入套件

  3. 按一下 [ 入] 按鈕,將專案新增至您的專案。

  4. 移至 [專案] 檢視中[外掛程式] 底下的 [儲存體] 資料夾,並選取下列外掛程式:

    • Microsoft.Data.Edm
    • Microsoft.Data.OData
    • Microsoft.WindowsAzure.Storage
    • Newtonsoft.Json
    • System.Spatial

    選取外掛程式

  5. 選取 這些特定外掛程式 後, 取消核取[任何平臺 ],然後 取消核取[WSAPlayer ],然後按一下 [ 套用]。

    套用平臺變更

    注意

    您要將這些特定外掛程式標示為只能在 Unity 編輯器中使用。 這是因為 WSA 資料夾中有不同版本的相同外掛程式,將在專案從 Unity 匯出之後使用。

  6. 在 [ 儲存體外掛程式] 資料夾中,只選取:

    • Microsoft.Data.Services.Client

      選取資料服務用戶端

  7. 核取 [平臺設定] 底下的 [不要處理]方塊,然後按一下 [套用]。

    不處理

    注意

    您正在標示此外掛程式「不要處理」,因為 Unity 元件修補程式處理此外掛程式時發生困難。 即使未處理外掛程式,外掛程式仍可運作。

第 14 章 - 在混合實境 Unity 專案中建立 TableToScene 類別

TableToScene類別與第 9 章中所述的類別相同。 遵循 第 9 章中所述的相同程式,在混合實境 Unity 專案中建立相同的類別。

完成本章之後, 您的兩個 Unity 專案 都會在主相機上設定此類別。

第 15 章 - 在 Mixed Reality Unity 專案中建立 NotificationReceiver 類別

您需要建立的第二個腳本是 NotificationReceiver,負責:

  • 在初始化時向通知中樞註冊應用程式。
  • 接聽來自通知中樞的通知。
  • 從收到的通知還原序列化物件資料。
  • 根據還原序列化的資料,在場景中移動 GameObjects。

若要建立 NotificationReceiver 腳本:

  1. [腳本 ] 資料夾內按一下滑鼠右鍵,按一下 [ 建立]、 [C# 腳本]。 將腳本命名為 NotificationReceiver

    建立新的 c# 腳本名稱為 NotificationReceiver

  2. 按兩下腳本加以開啟。

  3. 新增下列命名空間:

    //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
    
  4. 插入下列變數:

        /// <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-";
    
  5. 以您的通知中樞服務名稱取代 hubName 值,並以在 Azure 入口網站的 [存取原則] 索引標籤 Azure 通知中樞服務中找到的端點值取代 hubName 值, (請參閱下圖) 。

    插入通知中樞原則端點

  6. 現在新增 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());
        }
    
  7. 新增 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;
                }
            }
        }
    
  8. 下列方法 InitNotificationAsync () 會在初始化時向通知中樞服務註冊應用程式。 程式碼會標記為批註,因為 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;
            // }
        }
    
  9. 下列處理常式 Channel_PushNotificationReceived () 會在每次收到通知時觸發。 它會還原序列化通知,這會是已在傳統型應用程式上移動的 Azure 資料表實體,然後將 MR 場景中的對應 GameObject 移至相同的位置。

    重要

    程式碼會加上批註,因為程式碼會參考 Azure 傳訊程式庫,您將在 Visual Studio 中使用 Nuget 套件管理員建置 Unity 專案之後新增此程式庫。 因此,除非將 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;
        //    }
        //}
    
  10. 請記得在返回 Unity 編輯器之前儲存您的變更。

  11. 從 [階層] 面板按一下[主要相機],使其屬性會出現在Inspector中。

  12. 開啟 [ 腳本 ] 資料夾後,選取 NotificationReceiver 腳本,並將其拖曳至 主要相機。 結果應如下所示:

    將通知接收者腳本拖曳至相機

    注意

    如果您要針對Microsoft HoloLens進行此開發,您必須更新主要相機相機元件,以便:

    • 清除旗標:純色
    • 背景:黑色

第 16 章 - 將Mixed Reality專案建置至 UWP

本章與上一個專案的建置程式相同。 此專案的 Unity 區段一切都已完成,因此是時候從 Unity 建置它。

  1. 流覽至 [建置設定] ( [檔案>建置設定] ) 。

  2. 從 [ 建置設定 ] 功能表中,確定 已勾選 Unity C# 專案* (,這可讓您在建置) 之後編輯此專案中的腳本。

  3. 完成此動作之後,按一下 [建置]。

    顯示 [建置設定] 視窗的螢幕擷取畫面,其中右下方醒目提示 [建置] 按鈕。

  4. 檔案總管視窗隨即出現,提示您輸入要建置的位置。 按一下左上角的 [ 新增 資料夾]) ,並將其命名為 BUILDS,以建立新資料夾 (。

    建立組建資料夾

    1. 開啟新的 BUILDS 資料夾,然後再次使用 [ 新增 (資料夾]) 建立另一個資料夾,並將其命名 為NH_MR_App

      建立NH_MR_Apps資料夾

    2. 選取 NH_MR_App 。 按一下 [選取資料夾]。 專案需要一分鐘的時間才能建置。

  5. 在建置之後,檔案總管視窗會在新專案的位置開啟。

第 17 章 - 將 NuGet 套件新增至 UnityMRNotifHub 解決方案

警告

請記住,一旦您新增下列 NuGet 套件 (,並在下一 ) 取消批註程式碼之後,在 Unity 專案內重新開啟程式碼時,程式碼就會顯示錯誤。 如果您想要在 Unity 編輯器中返回並繼續編輯,則需要批註該錯誤的程式碼,然後在稍後重新批註,一旦您回到 Visual Studio。

完成混合實境建置之後,請流覽至您所建置的混合實境專案,然後按兩下該資料夾中的方案 (.sln) 檔案,以使用 Visual Studio 2017 開啟您的方案。 您現在必須新增 WindowsAzure.Messaging.managed NuGet 套件;這是用來從通知中樞接收通知的程式庫。

若要匯入 NuGet 套件:

  1. 方案總管中,以滑鼠右鍵按一下您的解決方案

  2. 按一下 [管理 NuGet 套件]。

    開啟 nuget 管理員

  3. 選取 [ 流覽] 索引標籤,然後搜尋 WindowsAzure.Messaging.managed

    尋找 Windows Azure 傳訊套件

  4. 選取結果 (,如下所示) ,然後在右側的視窗中,選取 [專案] 旁的核取方塊。 這會在 Project旁邊的核取方塊中加上核取方塊,以及 Assembly-CSharpUnityMRNotifHub 專案旁的核取方塊。

    刻度所有專案

  5. 最初提供的版本 可能與 這個專案不相容。 因此,按一下 [ 版本] 旁的下拉式功能表,然後按一下 [版本 0.1.7.9],然後按一下 [ 安裝]。

  6. 您現在已完成安裝 NuGet 套件。 尋找您在 NotificationReceiver 類別中輸入的批註程式碼,並移除批註。

第 18 章 - 編輯 UnityMRNotifHub 應用程式,NotificationReceiver 類別

在新增 NuGet 套件之後,您必須 取消批註NotificationReceiver 類別內的一些程式碼。

這包括:

  1. 頂端的命名空間:

    using Microsoft.WindowsAzure.Messaging;
    
  2. 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;
            }
        }
    

警告

上述程式碼有批註:請確定您不小心 取消批 注 (批註,因為如果您有!) ,程式碼將不會編譯。

  1. 最後, 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 章 - 將混合實境專案與市集應用程式產生關聯

您現在必須將 混合實境 專案與您在實驗室開始時所建立的市集應用程式產生關聯。

  1. 開啟解決方案。

  2. 以滑鼠右鍵按一下 [方案總管] 面板中的 [UWP 應用程式專案]、移至 [集] 和 [將應用程式與市集建立關聯...]。

    開啟存放區關聯

  3. 新的視窗隨即出現,稱為將 您的應用程式與 Windows 市集建立關聯。 按一下 [下一步] 。

    移至下一個畫面

  4. 它會載入與您登入之帳戶相關聯的所有應用程式。 如果您未登入您的帳戶,您可以在此頁面 登入

  5. 尋找您在本教學課程開頭建立的 市集應用程式名稱 ,然後加以選取。 然後按一下 [下一步] 。

    尋找並選取您的市集名稱

  6. 按一下 [關聯]

    建立應用程式關聯

  7. 您的應用程式現在已與市集應用程式 相關聯 。 這是啟用通知的必要專案。

第 20 章 - 部署 UnityMRNotifHub 和 UnityDesktopNotifHub 應用程式

這一章可能會讓兩個人更容易,因為結果會包含兩個應用程式執行、一個在您的電腦桌面上執行,另一個是在沉浸式頭戴式裝置內執行。

沉浸式頭戴裝置應用程式正在等候接收對場景的變更 (本機 GameObjects) 的位置變更,而傳統型應用程式將會變更其本機場景 (位置變更) ,這會共用給 MR 應用程式。 請先部署 MR 應用程式,後面接著傳統型應用程式,以便接收者開始接聽。

若要在本機電腦上部署 UnityMRNotifHub 應用程式:

  1. Visual Studio 2017中開啟UnityMRNotifHub應用程式的解決方案檔案。

  2. [解決方案平臺]中,選取 [x86]、[本機電腦]。

  3. 在 [ 方案組態 ] 中,選取 [ 偵錯]。

    顯示工具列中 [方案組態] 設定為 [偵錯] 的螢幕擷取畫面。

  4. 移至 [建置] 功能表 ,然後按一下 [ 部署方案 ] 以側載應用程式到您的電腦。

  5. 您的應用程式現在應該會出現在已安裝的應用程式清單中,準備好啟動。

若要在本機電腦上部署 UnityDesktopNotifHub 應用程式:

  1. Visual Studio 2017中開啟UnityDesktopNotifHub應用程式的解決方案檔案。

  2. [解決方案平臺]中,選取 [x86]、[本機電腦]。

  3. 在 [ 方案組態 ] 中,選取 [ 偵錯]。

    顯示 [解決方案組態] 設定為 [偵錯] 的螢幕擷取畫面。

  4. 移至 [建置] 功能表 ,然後按一下 [ 部署方案 ] 以側載應用程式到您的電腦。

  5. 您的應用程式現在應該會出現在已安裝的應用程式清單中,準備好啟動。

  6. 啟動混合實境應用程式,後面接著傳統型應用程式。

執行這兩個應用程式後,使用滑鼠左鍵) ,在桌面場景中移動物件 (。 這些位置變更將會在本機進行、序列化,並傳送至函式 App Service。 函式 App Service 接著會隨著通知中樞更新資料表。 收到更新之後,通知中樞會將更新的資料直接傳送到所有已註冊的應用程式 (,在此案例中,沉浸式頭戴裝置應用程式) ,然後還原序列化傳入資料,然後將新的位置資料套用至本機物件,並將它們移至場景。

您已完成 Azure 通知中樞應用程式

恭喜,您已建置混合實境應用程式,利用 Azure 通知中樞服務並允許應用程式之間的通訊。

最終產品 -end

額外練習

練習 1

您可以瞭解如何變更 GameObjects 的色彩,並將該通知傳送給檢視場景的其他應用程式?

練習 2

您可以將 GameObjects 的移動新增至 MR 應用程式,並在傳統型應用程式中查看更新的場景嗎?