HoloLens (第 1 代) 和 Azure 306:串流影片


注意

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


Windows Mixed Reality V R 範例的螢幕擷取畫面。Windows Mixed Reality V R 體驗的螢幕擷取畫面。

在此課程中,您將瞭解如何將 Azure 媒體服務連線至Windows Mixed Reality VR 體驗,以允許在沉浸式頭戴裝置上播放 360 度視訊。

Azure 媒體服務 是一組服務,可讓您廣播品質的視訊串流服務,以在現今最熱門的行動裝置上觸達較大的物件。 如需詳細資訊,請流覽 Azure 媒體服務頁面

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

  1. 透過Azure 媒體服務Azure 儲存體擷取 360 度影片。

  2. 在 Unity 場景中顯示擷取的 360 度影片。

  3. 在兩個場景之間巡覽,其中含有兩個不同的影片。

在您的應用程式中,您必須先瞭解如何將結果與您的設計整合。 本課程旨在教導您如何整合 Azure 服務與您的 Unity 專案。 您的工作是使用此課程取得的知識來增強混合實境應用程式。

裝置支援

課程 HoloLens 沉浸式頭戴裝置
MR 和 Azure 306:串流視訊 ✔️

必要條件

注意

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

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

在您開始使用 Intune 之前

  1. 若要避免建置此專案時發生問題,強烈建議您在根資料夾或近根資料夾中建立本教學課程中提及的專案, (長資料夾路徑可能會導致建置時間) 的問題。

  2. 設定及測試您的Mixed Reality沈浸式頭戴式裝置。

    注意

    不需要 此課程的動作控制器。 如果您需要支援設定沈浸式頭戴式裝置,請按一下如何設定Windows Mixed Reality的連結

第 1 章 - Azure 入口網站:建立 Azure 儲存體帳戶

若要使用Azure 儲存體服務,您必須在Azure 入口網站中建立及設定儲存體帳戶

  1. 登入 Azure 入口網站

    注意

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

  2. 登入之後,按一下左側功能表中的 [ 儲存體帳戶 ]。

    Azure 入口網站功能表的螢幕擷取畫面。儲存體帳戶已醒目提示。

  3. 在 [ 儲存體帳戶] 索引卷 標上,按一下 [ 新增]。

    儲存體帳戶對話方塊的螢幕擷取畫面。[新增] 已醒目提示。

  4. 在 [ 建立儲存體帳戶] 索引卷 標中:

    1. 插入帳戶 的 [名稱 ],請注意此欄位只接受數位和小寫字母。

    2. 針對 [部署模型], 選取 [資源管理員]。

    3. 針對 [帳戶種類],選取 [ 儲存體 (一般用途 v1)

    4. 針對[效能],選取[標準]。*

    5. 針對 [ 寫] 選取 [ 本機備援儲存體 (LRS)

    6. [安全傳輸] 保留為 [已停用]。

    7. 選取 [訂用帳戶] 。

    8. 選擇 資源群組 或建立新的群組。 資源群組提供一種方式來監視、控制存取、布建和管理 Azure 資產集合的計費。

    9. 如果您要建立新的資源群組) ,請判斷資源群組的位置 (。 在理想情況下,位置會位於應用程式執行所在的區域中。 某些 Azure 資產僅適用于特定區域。

  5. 您必須確認您已瞭解此服務適用的條款及條件。

    建立儲存體帳戶頁面的螢幕擷取畫面。

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

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

    部署成功通知的螢幕擷取畫面。

  8. 此時,您不需要遵循資源,只要移至下一章即可。

第 2 章 - Azure 入口網站:建立媒體服務

若要使用 Azure 媒體服務,您必須將服務的實例設定為可供您的應用程式使用, (其中帳戶持有者必須是管理員) 。

  1. 在 Azure 入口網站中,按一下左上角的 [ 建立資源 ],然後搜尋 媒體服務, 然後按 Enter鍵。 您想要的資源目前有一個粉紅色圖示;按一下此選項,以顯示新的頁面。

    Azure 入口網站的螢幕擷取畫面。[媒體服務] 選項會反白顯示。

  2. 新頁面將提供 媒體服務的描述。 在此提示的左下方,按一下 [ 建立 ] 按鈕,以建立與此服務的關聯。

    Azure 入口網站的螢幕擷取畫面。[建立] 按鈕會反白顯示。

  3. 按一下 [ 建立 面板] 之後,即會出現您需要提供新媒體服務的一些詳細資料:

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

    2. 選取 [訂用帳戶] 。

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

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

    1. 如果您要建立新的資源群組) ,請判斷資源群組的位置 (。 在理想情況下,位置會位於應用程式執行所在的區域中。 某些 Azure 資產僅適用于特定區域。

    2. 針對 [ 儲存體帳戶] 區段,按一下 [ 請選取...] 區段,然後按一下您在上一章中建立的 儲存體帳戶

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

    4. 按一下 [建立]。

      [建立媒體服務帳戶] 頁面的螢幕擷取畫面。

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

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

    入口網站功能表中通知圖示的螢幕擷取畫面。

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

    成功部署通知的螢幕擷取畫面。

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

  8. 在新的 [媒體服務] 頁面的左側面板中,按一下 [ 資產 ] 連結,大約在一半向下。

  9. 在下一個頁面上,按一下頁面左上角的 [ 上傳]。

    [資產] 頁面的螢幕擷取畫面。[上傳] 和 [資產] 選項會反白顯示。

  10. 按一下 [資料夾 ] 圖示以流覽您的檔案,然後選取您想要串流的前 360 部影片。

    您可以遵循此 連結來下載範例影片

    上傳影片資產頁面的螢幕擷取畫面。

警告

長檔名可能會導致編碼器發生問題:因此為了確保影片沒有問題,請考慮縮短視訊檔案名的長度。

  1. 當影片完成上傳時,進度列會變成綠色。

    上傳影片資產進度列的螢幕擷取畫面。

  2. 按一下上方 (yourservicename - Assets) 的文字,返回 [ 資產] 頁面。

  3. 您會發現您的影片已成功上傳。 按一下它。

    [資產] 頁面的螢幕擷取畫面。影片 1 點 M P 4 已醒目提示。

  4. 您重新導向至的頁面會顯示影片的詳細資訊。 若要能夠使用您的視訊,您必須將其編碼,方法是按一下頁面左上方的 [編碼 ] 按鈕。

    資產頁面的螢幕擷取畫面。編碼按鈕會反白顯示。

  5. 新的面板會出現在右側,您可以在其中設定檔案的編碼選項。 (某些屬性預設會設定下列屬性) :

    1. 媒體編碼器名稱媒體編碼器標準

    2. 編碼預設 內容自適性多重位元速率 MP4

    3. 作業名稱媒體編碼器標準處理Video1.mp4

    4. 輸出媒體資產名稱Video1.mp4 -- 媒體編碼器標準編碼

      編碼資產頁面的螢幕擷取畫面。

  6. 按一下 [ 建立 ] 按鈕。

  7. 您會注意到 已新增編碼作業的列,按一下該列,隨即會出現一個面板,其中顯示 [編碼進度]。

    已新增標示編碼作業之通知列的螢幕擷取畫面。

    編碼器處理頁面的螢幕擷取畫面。

  8. 等候作業完成。 完成後,請放心地關閉面板,該面板右上方有 'X'。

    進度列的螢幕擷取畫面,其中狀態為已完成。

    媒體編解碼器處理頁面頂端功能表的螢幕擷取畫面。

    重要

    這需要的時間取決於視訊的檔案大小而定。 此程式可能需要很長的時間。

  9. 既然已建立視訊的編碼版本,您可以發佈它以使其可供存取。 若要這樣做,請按一下藍色連結 [資產 ] 返回 [資產] 頁面。

    Azure 入口網站的螢幕擷取畫面。資產連結會反白顯示。

  10. 您會看到您的影片以及另一個影片,也就是 資產類型 多位元率 MP4

    Microsoft Azure 資產功能表的螢幕擷取畫面。

    注意

    您可能會注意到,新資產與初始視訊一起為 Unknown,且其 大小為 '0' 個位元組,只要重新整理視窗即可更新。

  11. 按一下此新資產。

    目錄清單資產的螢幕擷取畫面。

  12. 您會看到類似您先前使用的面板,只是這是不同的資產。 按一下位於頁面頂端的 [發佈 ] 按鈕。

    頂端功能表列的螢幕擷取畫面。[發佈] 按鈕會反白顯示。

  13. 系統會提示您設定 定位器,這是資產中的檔案/秒進入點。 針對您的案例,請設定下列屬性:

    1. 定位器類型>漸進式

    2. 從您目前日期到未來 (100 年的時間,將會為您設定日期和時間) 。 保持原樣,或將其變更為適合。

    注意

    如需定位器的詳細資訊,以及您可以選擇的內容,請造訪 Azure 媒體服務檔

  14. 在該面板底部,按一下 [ 新增 ] 按鈕。

    顯示具有要發行資產之目錄清單的螢幕擷取畫面。

  15. 您的影片現已發佈,而且可以使用其端點進行串流處理。 頁面的下一步是 [ 檔案] 區段。 這是視訊不同編碼版本的位置。 選取下圖中 (的最高解析度,也就是 1920x960 檔案) ,然後會出現右側的面板。 您可以在該處找到 下載 URL。 複製此 端點 ,因為您稍後會在程式碼中使用。

    Microsoft Azure 檔案儲存體 區段的螢幕擷取畫面。

    資產資訊頁面的螢幕擷取畫面。

    注意

    您也可以按 [ 播放 ] 按鈕來播放影片並進行測試。

  16. 您現在必須上傳您將在此實驗室中使用的第二個影片。 請遵循上述步驟,針對第二個影片重複相同的程式。 請確定您也複製第二個 端點 。 使用下列 連結來下載第二個影片

  17. 發佈這兩個影片之後,您就可以移至下一章。

第 3 章 - 設定 Unity 專案

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

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

    Unity 專案索引標籤的螢幕擷取畫面。[新增] 按鈕會反白顯示。

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

    Unity 新專案頁面的螢幕擷取畫面。

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

    外部腳本編輯器功能表的螢幕擷取畫面。已選取 Visual Studio 2017。

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

  5. 也請確定:

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

    2. 組建類型 設定為 D3D。

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

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

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

    6. 別擔心現在設定 場景 ,因為您稍後會設定這些場景。

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

      Unity 組建設定畫面的螢幕擷取畫面。

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

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

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

      1. 腳本運行時間版本 應該是 穩定 (.NET 3.5 對等) 。

      2. 腳本後端 應該是 .NET。

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

        顯示 [通用 Windows 平臺] 頁面 [設定] 的螢幕擷取畫面。

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

      Unity X R 設定畫面的螢幕擷取畫面。

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

      • InternetClient

        [功能] 畫面的螢幕擷取畫面。已檢查網際網路用戶端。

  8. 進行這些變更之後,請關閉 [ 建置設定] 視窗。

  9. 儲存專案 儲存專案

第 4 章 - 匯入 InsideOutSphere Unity 套件

重要

如果您想要略過本課程的 Unity 設定 元件,並繼續進入程式碼,請隨意下載此 .unitypackage、將它匯入您的專案作為 自訂套件,然後從 第 5 章繼續進行。 您仍然需要建立 Unity 專案。

在此課程中,您必須下載名為 InsideOutSphere.unitypackage的 Unity 資產套件。

如何匯入 unitypackage

  1. 在 Unity 儀表板前面,按一下畫面頂端功能表中的 [ 資產 ],然後按一下 [ 匯入套件自訂套件 >]。

    資產功能表的螢幕擷取畫面。匯入套件功能表已開啟。已選取 [自訂套件]。

  2. 使用檔案選擇器選取 InsideOutSphere.unitypackage 套件,然後按一下 [ 開啟]。 此資產的元件清單將會顯示給您。 按一下 [ 入] 以確認匯入。

    [匯入 Unity 套件] 畫面的螢幕擷取畫面。

  3. 匯入完成後,您會發現已將三個新資料夾 [材質]、[ 模型] 和 [ 預製專案] 新增至 [ 資產 ] 資料夾。 這種資料夾結構通常適用于 Unity 專案。

    assets 資料夾的螢幕擷取畫面。

    1. 開啟 Models 資料夾,您會看到 InsideOutSphere 模型已匯入。

    2. [材質] 資料夾中,您會發現 InsideOutSpheres 材質 lambert1,以及名為 ButtonMaterial的材質,由 GazeButton 使用,您很快就會看到該材質。

    3. Prefabs資料夾包含InsideOutSphere預製專案,其中包含InsideOutSphere模型GazeButton

    4. 不包含任何程式碼,您將遵循本課程撰寫程式碼。

  4. [階層]中,選取 [主要相機 ] 物件,並更新下列元件:

    1. 轉換

      1. Position = X: 0, Y: 0, Z: 0.

      2. 旋轉 = X: 0, Y: 0, Z: 0。

      3. 縮放 X:1、 Y:1、 Z:1。

    2. 相機

      1. 清除旗標:純色。

      2. 裁剪平面:近:0.1、遠:6。

        [偵測器] 畫面的螢幕擷取畫面。

  5. 流覽至 Prefab 資料夾,然後將 InsideOutSphere 預製專案拖曳至 [ 階層 面板]。

    Prefab 資料夾功能表和開發人員環境的螢幕擷取畫面。

  6. 按一下階層旁邊的小箭號,展開Hierarchy中的InsideOutSphere物件。 您會在名為GazeButton的子物件下方看到一個物件。 這會用來變更場景和影片。

    階層索引標籤的螢幕擷取畫面。

  7. 在 [偵測器] 視窗中,按一下 InsideOutSphere的 [轉換] 元件,確定已設定下列屬性:

轉換 - 位置

X Y Z
0 0 0

轉換 - 旋轉

X Y Z
0 -50 0

轉換 - 調整

X Y Z
0 0 0

[內部球體] 開啟 [偵測器] 畫面的螢幕擷取畫面。

  1. 按一下 GazeButton 子物件,並設定其 Transform ,如下所示:

轉換 - 位置

X Y Z
3.6 1.3 0

轉換 - 旋轉

X Y Z
0 0 0

轉換 - 調整

X Y Z
1 1 1

開啟場景索引標籤的螢幕擷取畫面。

第 5 章 - 建立 VideoController 類別

VideoController類別會裝載兩個影片端點,用來從 Azure 媒體服務串流內容。

若要建立此類別:

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

    資產資料夾功能表的螢幕擷取畫面。[建立] 功能表隨即開啟,並已選取資料夾。

    專案索引標籤的螢幕擷取畫面。已選取 [資產] 資料夾。

  2. 按兩下 [腳本 ] 資料夾以開啟它。

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

    名為影片控制器的檔案螢幕擷取畫面。

  4. 按兩下新的VideoController腳本,以使用Visual Studio 2017加以開啟。

    影片控制器檔案程式碼的螢幕擷取畫面。

  5. 更新程式碼檔案頂端的命名空間,如下所示:

    using System.Collections;
    using UnityEngine;
    using UnityEngine.SceneManagement;
    using UnityEngine.Video;
    
  6. VideoController 類別中輸入下列變數,以及 Awake () 方法:

        /// <summary> 
        /// Provides Singleton-like behaviour to this class. 
        /// </summary> 
        public static VideoController instance; 
    
        /// <summary> 
        /// Reference to the Camera VideoPlayer Component.
        /// </summary> 
        private VideoPlayer videoPlayer; 
    
        /// <summary>
        /// Reference to the Camera AudioSource Component.
        /// </summary> 
        private AudioSource audioSource; 
    
        /// <summary> 
        /// Reference to the texture used to project the video streaming 
        /// </summary> 
        private RenderTexture videoStreamRenderTexture;
    
        /// <summary>
        /// Insert here the first video endpoint
        /// </summary>
        private string video1endpoint = "-- Insert video 1 Endpoint here --";
    
        /// <summary>
        /// Insert here the second video endpoint
        /// </summary>
        private string video2endpoint = "-- Insert video 2 Endpoint here --";
    
        /// <summary> 
        /// Reference to the Inside-Out Sphere. 
        /// </summary> 
        public GameObject sphere;
    
        void Awake()
        {
            instance = this;
        }
    
  7. 現在是從 Azure 媒體服務影片輸入端點的時間:

    1. 第一個進入 video1endpoint 變數。

    2. 第二個進入 video2endpoint 變數。

    警告

    在 Unity 中使用 HTTPs 的已知問題,版本為 2017.4.1f1。 如果影片在播放時發生錯誤,請嘗試改用 'HTTP'。

  8. 接下來,必須編輯 Start () 方法。 每次使用者切換場景 (時,都會觸發這個方法,藉由查看 [注視按鈕] 來切換視訊) 。

        // Use this for initialization
        void Start()
        {
            Application.runInBackground = true;
            StartCoroutine(PlayVideo());
        }
    
  9. Start () 方法之後,插入PlayVideo () IEnumerator方法,這會用來順暢地啟動影片 (,因此不會看到任何雜亂) 。

        private IEnumerator PlayVideo()
        {
            // create a new render texture to display the video 
            videoStreamRenderTexture = new RenderTexture(2160, 1440, 32, RenderTextureFormat.ARGB32);
    
            videoStreamRenderTexture.Create();
    
            // assign the render texture to the object material 
            Material sphereMaterial = sphere.GetComponent<Renderer>().sharedMaterial;
    
            //create a VideoPlayer component 
            videoPlayer = gameObject.AddComponent<VideoPlayer>();
    
            // Set the video to loop. 
            videoPlayer.isLooping = true;
    
            // Set the VideoPlayer component to play the video from the texture 
            videoPlayer.renderMode = VideoRenderMode.RenderTexture;
    
            videoPlayer.targetTexture = videoStreamRenderTexture;
    
            // Add AudioSource 
            audioSource = gameObject.AddComponent<AudioSource>();
    
            // Pause Audio play on Awake 
            audioSource.playOnAwake = true;
            audioSource.Pause();
    
            // Set Audio Output to AudioSource 
            videoPlayer.audioOutputMode = VideoAudioOutputMode.AudioSource;
            videoPlayer.source = VideoSource.Url;
    
            // Assign the Audio from Video to AudioSource to be played 
            videoPlayer.EnableAudioTrack(0, true);
            videoPlayer.SetTargetAudioSource(0, audioSource);
    
            // Assign the video Url depending on the current scene 
            switch (SceneManager.GetActiveScene().name)
            {
                case "VideoScene1":
                    videoPlayer.url = video1endpoint;
                    break;
    
                case "VideoScene2":
                    videoPlayer.url = video2endpoint;
                    break;
    
                default:
                    break;
            }
    
            //Set video To Play then prepare Audio to prevent Buffering 
            videoPlayer.Prepare();
    
            while (!videoPlayer.isPrepared)
            {
                yield return null;
            }
    
            sphereMaterial.mainTexture = videoStreamRenderTexture;
    
            //Play Video 
            videoPlayer.Play();
    
            //Play Sound 
            audioSource.Play();
    
            while (videoPlayer.isPlaying)
            {
                yield return null;
            }
        }
    
  10. 這個類別所需的最後一個方法是 ChangeScene () 方法,這個方法將用來在場景之間交換。

        public void ChangeScene()
        {
            SceneManager.LoadScene(SceneManager.GetActiveScene().name == "VideoScene1" ? "VideoScene2" : "VideoScene1");
        }
    

    提示

    ChangeScene () 方法會使用稱為條件運算子的方便 C# 功能。 這允許檢查條件,然後根據檢查的結果傳回的值,全部都在單一語句內。 請遵循此 連結以深入瞭解條件運算子

  11. 在 Visual Studio 中儲存變更,再返回 Unity。

  12. 回到 Unity 編輯器,按一下並拖曳VideoController類別 [from]{.underline} [腳本] 資料夾到[階層面板] 中的 [主要相機] 物件。

  13. 按一下 [主要相機 ] 並查看 [偵測器面板]。 您會注意到,在新增的腳本元件中,有一個欄位具有空白值。 這是以程式碼內公用變數為目標的參考欄位。

  14. InsideOutSphere 物件從 [階層面板 ] 拖曳至 Sphere 位置,如下圖所示。

    階層功能表的螢幕擷取畫面。已選取主要相機。Sphere 位置的螢幕擷取畫面。

第 6 章 - 建立注視類別

此類別負責建立將投影自主要相機Raycast,以偵測使用者正在查看的物件。 在此情況下, Raycast 必須識別使用者是否在場景中查看 GazeButton 物件,並觸發行為。

若要建立此類別:

  1. 移至您先前建立的 [腳本 ] 資料夾。

  2. 以滑鼠右鍵按一下 [專案 面板], [建立C# 腳本]。 將腳本命名為 Gaze

  3. 按兩下新的注視腳本,以使用Visual Studio 2017加以開啟。

  4. 請確定下列命名空間位於腳本頂端,並移除任何其他命名空間:

    using UnityEngine;
    
  5. 然後在 Gaze 類別內新增下列變數:

        /// <summary> 
        /// Provides Singleton-like behaviour to this class. 
        /// </summary> 
        public static Gaze instance;
    
        /// <summary> 
        /// Provides a reference to the object the user is currently looking at. 
        /// </summary> 
        public GameObject FocusedGameObject { get; private set; }
    
        /// <summary> 
        /// Provides a reference to compare whether the user is still looking at 
        /// the same object (and has not looked away). 
        /// </summary> 
        private GameObject oldFocusedObject = null;
    
        /// <summary> 
        /// Max Ray Distance 
        /// </summary> 
        float gazeMaxDistance = 300;
    
        /// <summary> 
        /// Provides whether an object has been successfully hit by the raycast. 
        /// </summary> 
        public bool Hit { get; private set; }
    
  6. 現在必須新增 Awake () Start () 方法的程式碼。

        private void Awake()
        {
            // Set this class to behave similar to singleton 
            instance = this;
        }
    
        void Start()
        {
            FocusedGameObject = null;
        }
    
  7. Update () 方法中新增下列程式碼,以投影 Raycast 並偵測目標點擊:

        void Update()
        {
            // Set the old focused gameobject. 
            oldFocusedObject = FocusedGameObject;
            RaycastHit hitInfo;
    
            // Initialise Raycasting. 
            Hit = Physics.Raycast(Camera.main.transform.position, Camera.main.transform.forward, out hitInfo, gazeMaxDistance);
    
            // Check whether raycast has hit. 
            if (Hit == true)
            {
                // Check whether the hit has a collider. 
                if (hitInfo.collider != null)
                {
                    // Set the focused object with what the user just looked at. 
                    FocusedGameObject = hitInfo.collider.gameObject;
                }
                else
                {
                    // Object looked on is not valid, set focused gameobject to null. 
                    FocusedGameObject = null;
                }
            }
            else
            {
                // No object looked upon, set focused gameobject to null.
                FocusedGameObject = null;
            }
    
            // Check whether the previous focused object is this same 
            // object (so to stop spamming of function). 
            if (FocusedGameObject != oldFocusedObject)
            {
                // Compare whether the new Focused Object has the desired tag we set previously. 
                if (FocusedGameObject.CompareTag("GazeButton"))
                {
                    FocusedGameObject.SetActive(false);
                    VideoController.instance.ChangeScene();
                }
            }
        }
    
  8. 在 Visual Studio 中儲存變更,再返回 Unity。

  9. 按一下 [注視] 類別,然後將 [腳本] 資料夾拖曳至 [階層 面板] 中的 [主要相機] 物件。

第 7 章 - 設定兩個 Unity 場景

本章的目的是要設定兩個場景,每個場景都會裝載要串流的視訊。 您將會複製您已建立的場景,因此您不需要再次設定它,不過您接著會編輯新的場景,讓 GazeButton 物件位於不同的位置,並有不同的外觀。 這是示範如何在場景之間變更。

  1. 若要這樣做,請移至 [ 檔案 > 儲存場景...]。隨即會出現儲存視窗。 按一下 [ 新增資料夾] 按鈕。

    第 7 章 - 設定兩個 Unity 場景

  2. 將資料夾命名為 Scenes

  3. [ 儲存場景 ] 視窗仍會開啟。 開啟新建立的 Scenes 資料夾。

  4. 在 [ 檔案名: 文字] 欄位中,輸入 VideoScene1,然後按 [ 儲存]。

  5. 回到 Unity,開啟 您的 Scenes 資料夾,然後以滑鼠左鍵按一下 VideoScene1 檔案。 使用鍵盤,然後按 Ctrl + D ,您將會複製該場景

    提示

    您也可以流覽至 [編輯 > 重複專案] 來執行重複命令。

  6. Unity 會自動遞增場景名稱編號,但仍然檢查它,以確保它符合先前插入的程式碼。

    您應該會有 VideoScene1VideoScene2

  7. 使用您的兩個場景,移至 [ 檔案 > 建置設定]。 開啟 [ 建置設定 ] 視窗後,將您的場景拖曳至 [ 建置] 區段的 [場景 ]。

    [建置設定] 視窗的螢幕擷取畫面。

    提示

    您可以從 [場景 ] 資料夾選取這兩個場景,方法是按住 Ctrl 按鈕,然後以滑鼠左鍵按一下每個場景,最後拖曳兩者。

  8. 關閉 [ 建置設定 ] 視窗,然後按兩下 VideoScene2

  9. 開啟第二個場景後,按一下InsideOutSphereGazeButton子物件,並設定其 Transform,如下所示:

轉換 - 位置

X Y Z
0 1.3 3.6

轉換 - 旋轉

X Y Z
0 0 0

轉換 - 調整

X Y Z
1 1 1
  1. 在仍然選取GazeButton子系的情況下,查看偵測器和網格篩選。 按一下 [網格 參考] 欄位旁邊的小目標:

    [注視] 按鈕的偵測器畫面螢幕擷取畫面。

  2. [ 選取網格 ] 快顯視窗隨即出現。 從[資產] 清單中按兩下Cube網格。

    [選取網格] 快顯視窗的螢幕擷取畫面。

  3. Mesh 篩選條件將會更新,現在會是Cube。 現在,按一下Sphere 碰撞器旁邊的齒輪圖示,然後按一下[移除元件],從這個物件中刪除碰撞器。

    Sphere 碰撞器功能表的螢幕擷取畫面。已選取 [移除元件]。

  4. 選取[GazeButton] 後,按一下Inspector底部的 [新增元件] 按鈕。 在搜尋欄位中,輸入 塊和 Box Collider 將會是選項 -- 按一下此選項,將 Box Collider 新增至 您的 GazeButton 物件。

    [新增元件] 搜尋方塊的螢幕擷取畫面。

  5. GazeButton現在已部分更新,看起來會不同,不過,您現在會建立新的Material,讓它看起來完全不同,而且更容易辨識為不同于第一個場景中的物件。

  6. 流覽至[專案面板] 內的[材質]資料夾。 複製ButtonMaterial Material (在鍵盤上按Ctrl + D,或以滑鼠左鍵按一下[材質],然後從 [編輯檔案] 功能表選項選取 [重複) ]。

    專案索引標籤中 [材質] 資料夾的螢幕擷取畫面。已選取重複的編輯功能表螢幕擷取畫面。

  7. 選取這裡名為ButtonMaterial 1的新ButtonMaterial Material () ,然後在[偵測器] 內按一下[Albedo色彩] 視窗。 隨即會出現快顯視窗,您可以在其中選取另一個色彩, (選擇您想要) ,然後關閉快顯視窗。 Material 會是自己的實例,而且與原始實例不同。

    色彩選取範圍快顯的螢幕擷取畫面。

  8. 將新 材質 拖曳到 GazeButton 子系,以立即完整更新其外觀,以便輕鬆地與第一個場景按鈕區別。

    專案編輯器場景索引標籤的螢幕擷取畫面。

  9. 此時,您可以在編輯器中測試專案,再建置 UWP 專案。

    • 編輯器中按[播放] 按鈕,並戴上您的頭戴式裝置。

      顯示播放、暫停和略過按鈕的螢幕擷取畫面。播放按鈕會反白顯示。

  10. 查看兩個 GazeButton 物件,以在第一個和第二個視訊之間切換。

第 8 章 - 建置 UWP 解決方案

確定編輯器沒有錯誤之後,您就可以開始建置。

若要建置:

  1. 按一下 [ 檔案 > 儲存] 以儲存目前的場景。

  2. 核取名為 Unity C# 專案的 方塊 (這很重要,因為它可讓您在建置完成後編輯類別) 。

  3. 移至 [ 檔案 > 建置設定],按一下 [ 建置]。

  4. 系統會提示您選取您要建置解決方案的資料夾。

  5. 建立 BUILDS 資料夾,並在該資料夾中建立另一個具有所選適當名稱的資料夾。

  6. 按一下您的新資料夾,然後按一下 [ 選取資料夾],以便選擇該資料夾,以在該位置開始建置。

    反白顯示的 BUILDS 資料夾螢幕擷取畫面。反白顯示 [影片串流建置] 資料夾的螢幕擷取畫面。

  7. 一旦 Unity 完成建置 (可能需要一些時間) ,它會在組建的位置開啟檔案總管視窗。

第 9 章 - 在本機電腦上部署

建置完成後,檔案總管視窗會出現在組建的位置。 開啟您命名並建置到的資料夾,然後按兩下該資料夾中的方案 (.sln) 檔案,以使用 Visual Studio 2017 開啟您的方案。

唯一要做的事是將您的應用程式部署至電腦 (或 本機電腦) 。

若要部署至本機電腦:

  1. Visual Studio 2017中,開啟剛建立的方案檔案。

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

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

    [方案組態] 功能表的螢幕擷取畫面。

  4. 您現在需要將任何套件還原到您的解決方案。 以滑鼠右鍵按一下您的 方案,然後按一下 [還原方案的 NuGet 套件...

    注意

    這是因為 Unity 所建置的套件必須以目標為目標,才能使用本機電腦參考。

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

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

    已安裝應用程式清單的螢幕擷取畫面。

當您執行Mixed Reality應用程式時,您會在應用程式內使用的InsideOutSphere模型內。 此球體會是影片將串流到其中,並提供 360 度檢視的傳入視訊 (,此視訊是針對這種觀點) 所錄製。 如果視訊需要幾秒鐘的時間載入,您的應用程式會受限於可用的網際網路速度,因為需要擷取並下載影片,因此要串流到您的應用程式。 當您準備好時,請變更場景並開啟第二個影片,方法是在紅色球體上查看! 然後放心地返回,使用第二個場景中的藍色立方體!

您已完成的 Azure 媒體服務應用程式

恭喜,您已建置混合實境應用程式,利用 Azure 媒體服務串流 360 個影片。

範例混合實境應用程式的螢幕擷取畫面。

混合實境應用程式範例的螢幕擷取畫面。

Bonus 練習

練習 1

完全可以使用單一場景來變更本教學課程中的影片。 實驗您的應用程式,並將其設為單一場景! 或許甚至將另一個影片新增至混合。

練習 2

試驗 Azure 和 Unity,並嘗試實作應用程式自動選取具有不同檔案大小的視訊的能力,視網際網路連線的強度而定。