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


注意

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


final product -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 Project。 您的工作是使用此課程取得的知識來增強混合實境應用程式。 本課程是獨立的教學課程,不會直接涉及任何其他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. 從 [儀表板] 中,按一下 [建立新的應用程式]。

    create an app

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

    reverse a name

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

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

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

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

    application registration portal

    警告

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

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

    your newly registered app

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

    application secrets

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

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

  1. 登入 Azure 入口網站

    注意

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

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

    search for notification hub

    注意

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

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

    create notification hubs instance

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

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

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

    3. 選取 [位置]。

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

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

    5. 選取適當的 訂用帳戶

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

    7. 選取 [建立]。

      fill in service details

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

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

    notification

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

    Screenshot that shows the 'Go to resource' button highlighted in the notification window.

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

    newly created hubs service

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

    copy down security details

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

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

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

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

    注意

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

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

    search for storage account

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

    create storage instance

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

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

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

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

    4. 選取適當的 位置

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

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

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

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

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

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

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

    11. 按一下 [建立]。

      fill in storage details

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

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

    new storage notification

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

    Screenshot that shows the 'Go to resource' button highlighted in the 'Deployment succeeded' window.

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

    Screenshot that shows where to select Tables.

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

    open Tables

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

    create new table

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

    new table created

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

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

  1. 開啟Visual Studio

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

    open cloud explorer

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

    注意

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

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

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

      find subscription

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

    open storage accounts

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

    open scene objects table

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

    add new table

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

    partition and row key

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

    add correct Values

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

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

    click ok when done

    警告

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

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

    first row

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

    add cube

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

    add cylinder

  14. 您的資料表現在看起來應該如下所示。

    table complete

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

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

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

首先,您需要建立可讓 Azure Function 載入所需程式庫的檔案。

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

    open notepad

  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鍵。

    search for function app

    注意

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

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

    function app instance

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

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

    2. 選取 [訂用帳戶] 。

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

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

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

    5. 針對OS,按一下 [Windows],就如同預期的平臺一樣。

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

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

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

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

    10. 按一下 [建立]。

      create new instance

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

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

    new notification

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

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

    Screenshot that shows 'Deployment succeeded' with the 'Go to resource' button highlighted.

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

    add new function

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

    custom function

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

    http put link

    重要

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

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

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

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

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

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

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

      Screenshot that shows the Storage account connection section with the 'New' hyperlink selected.

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

    create function

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

    update function code

  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. 接下來,按一下 < 頁面右側 (箭號) 圖示。

    open upload panel

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

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

    upload json

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

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

    integrate function

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

    open advanced editor

  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. 您的編輯器現在看起來應該像下圖:

    back to standard editor

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

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

    Table inputs

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

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

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

      Screenshot that shows the Storage Account window with 'Create new' highlighted in the panel to the right of the window.

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

      2. 您會發現已建立儲存體帳戶連線值。

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

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

      inputs complete

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

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

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

      check outputs

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

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

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

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

      output update

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

警告

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

Screenshot that shows the Outputs page with general information.

  1. 此時,您應該測試函式,以確保函式正常運作。 作法:

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

      Screenshot that shows the functions page with the newly created function highlighted.

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

      Screenshot of the functions page with 'Test' highlighted on the right side.

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

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

      Screenshot that shows the output logs of the test in the console area.

    警告

    如果上述測試失敗,您必須再次確認您已完全遵循上述步驟,特別是 整合面板中的設定。

第 7 章 - 設定桌面 Unity Project

重要

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

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

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

注意

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

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

    Screenshot of the Unity Projects window with the 'New' project icon highlighted in the upper right.

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

    create project

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

    set external VS tools

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

    switch platforms

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

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

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

    2. 組建類型 設定為 D3D

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

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

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

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

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

        Screenshot that shows the 'Add Open Scene' highlighted in the upper right.

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

        Screenshot that shows a new Scenes folder created with 'New folder' highlighted in the upper left.

      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 version

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

      • InternetClient

        Screenshot that shows InternetClient selected under Capabilities.

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

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

  10. 儲存場景並Project檔案>儲存場景/檔案> 儲存Project

    重要

    如果您想要略過此專案的 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 套件] 方塊中,您可以選取[外掛程式>儲存體下的所有專案。 取消核取所有其他專案,因為此課程不需要。

    import to package

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

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

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

uncheck Any platform

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

    apply platform dlls

    注意

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

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

    • Microsoft.Data.Services.Client

      set dont process for dlls

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

    apply no processing

    注意

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

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

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

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

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

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

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

若要建立此類別:

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

    create scripts folder

    create scripts folder 2

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

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

    Screenshot that shows how to create the new 'TableToScene' script.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 入口網站中 (請參閱下圖) 。

    fetch account key

  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. 從 [階層] 面板按一下[主要] 相機,使其屬性會出現在[偵測器] 中。

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

    add script to main camera

第 10 章 - 在 Desktop Unity Project 中建立 CloudScene 類別

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

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

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

若要建立第二個腳本:

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

    Screenshot that shows how to create the new 'CloudScene' script.rename 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 function 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腳本拖曳到Main 相機

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

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

      drag cloud script onto main camera

第 11 章 - 將桌面Project建置至 UWP

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

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

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

    Screenshot that shows the Build Settings window with Universal Windows Platform selected and the 'Build' button highlighted in the lower right.

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

    new folder for build

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

      folder name NH_Desktop_App

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

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

第 12 章 - 設定 Mixed Reality Unity Project

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

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

    Screenshot that shows the Unity Projects window with 'New' highlighted in the upper right.

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

    name UnityMRNotifHub

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

    set external editor to VS

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

    switch platforms to UWP

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

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

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

    2. 組建類型 設定為 D3D

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

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

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

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

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

        Screenshot that shows the Build Settings window with 'Add Open Scenes' button highlighted in the upper right.

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

        Screenshot that shows 'New folder' highlighted in the upper left in the Save Scene window.

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

        new scene - NH_MR_Scene

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

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

    open player settings

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

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

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

      2. 腳本後端應該是.NET

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

        api compatibility

    2. 進一步在面板下方,在XR 設定 (中找到下列發佈設定) ,刻度支援虛擬實境,確定已新增Windows Mixed Reality SDK

      update xr settings

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

      • InternetClient

        Screenshot that shows the Publishing Settings tab with InternetClient checked.

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

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

  10. 儲存場景並Project儲存>場景/檔案>儲存Project

    重要

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

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

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

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

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

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

    import package

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

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

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

    select plugins

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

    apply platform changes

    注意

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

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

    • Microsoft.Data.Services.Client

      select data services client

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

    dont process

    注意

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

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

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

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

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

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

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

若要建立 NotificationReceiver 腳本:

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

    create new c# scriptname it 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 值, (請參閱下圖) 。

    insert notification hubs policy endpoint

  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 傳訊程式庫,您會在使用 Nuget 封裝管理員 建置 Unity 專案之後,于Visual Studio內新增此程式庫。 因此,除非將 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. 從 [階層] 面板按一下[主要相機],使其屬性出現在[偵測器] 中。

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

    drag notification receiver script to camera

    注意

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

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

第 16 章 - 將Mixed Reality Project建置至 UWP

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

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

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

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

    Screenshot that shows the Build Settings window with the 'Build' button highlighted in the lower right.

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

    create builds folder

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

      create NH_MR_Apps folder

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

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

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

警告

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

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

若要匯入NuGet套件:

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

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

    open nuget manager

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

    find windows azure messaging package

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

    tick all projects

  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 章 - 將混合實境專案與Microsoft Store應用程式產生關聯

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

  1. 開啟解決方案。

  2. 以滑鼠右鍵按一下方案總管面板中的 UWP app Project、移至[Microsoft Store],以及 [將應用程式與Microsoft Store建立關聯...]。

    open store association

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

    go to the next screen

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

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

    find and select your store name

  6. 按一下 [關聯]

    associate the app

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

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

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

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

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

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

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

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

    Screenshot that shows the Solution Configuration set to 'Debug' in the toolbar.

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

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

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

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

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

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

    Screenshot that shows the Solution Configuration set to 'Debug'.

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

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

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

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

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

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

final product -end

額外練習

練習 1

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

練習 2

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