HoloLens(第一代)和 Azure 306 - 流视频


注意

混合现实学院教程在制作时考虑到了 HoloLens(第一代)和混合现实沉浸式头戴显示设备。 因此,对于仍在寻求这些设备的开发指导的开发人员而言,我们觉得很有必要保留这些教程。 我们不会在这些教程中更新 HoloLens 2 所用的最新工具集或集成相关的内容。 我们将维护这些教程,使之持续适用于支持的设备。 将来会发布一系列演示如何针对 HoloLens 2 进行开发的新教程。 此通知将在教程发布时通过指向这些教程的链接进行更新。


Screenshot of a Windows Mixed Reality V R example.Screenshot of a Windows Mixed Reality V R experience.

本课程介绍如何将 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 月)已经过测试和验证。 可随意使用最新软件(如安装工具一文所列的软件),但不应假设本课程中的信息会与你在比下列版本更高的软件中找到的内容完全一致。

建议在本课程中使用以下硬件和软件:

开始之前

  1. 为了避免在生成此项目时遇到问题,强烈建议在根文件夹或接近根的文件夹中创建本教程中提到的项目(长文件夹路径会在生成时导致问题)。

  2. 设置并测试混合现实沉浸式头戴显示设备。

    注意

    本课程不需要运动控制器。 如果在设置沉浸式头戴显示设备方面需要支持,请单击有关如何设置 Windows Mixed Reality 的链接

第 1 章 - Azure 门户:创建 Azure 存储帐户

若要使用 Azure 存储服务,你将需要在 Azure 门户中创建和配置“存储帐户”

  1. 登录到 Azure 门户

    注意

    如果你没有 Azure 帐户,需要创建一个。 如果你在课堂或实验室场景中跟着本教程学习,请让讲师或监督人员帮助设置你的新帐户。

  2. 登录后,在左侧菜单中单击“存储帐户”

    Screenshot of the Azure Portal menu. Storage accounts is highlighted.

  3. 在“存储帐户”选项卡上,单击“添加”

    Screenshot of the storage account dialog box. Add is highlighted.

  4. 在“创建存储帐户”选项卡中

    1. 为帐户插入名称,请注意,此字段仅接受数字和小写字母

    2. 对于“部署模型”,请选择“资源管理器”

    3. 对于“帐户类型”,请选择“存储(常规用途 v1)”

    4. 对于“性能”,请选择“标准”。*

    5. 对于“复制”,请选择“本地冗余存储(LRS)”

    6. 将“需要安全传输”保留为“已禁用”

    7. 选择一个“订阅” 。

    8. 选择一个资源组或创建一个新资源组。 通过资源组,可监视和预配 Azure 资产集合、控制其访问权限并管理其计费。

    9. 为资源组确定位置(如果正在创建新的资源组)。 理想情况下,此位置在运行应用程序的区域中。 某些 Azure 资产仅在特定区域可用。

  5. 需要确认了解应用于此服务的条款和条件。

    Screenshot of the create storage account page.

  6. 单击“创建”后,必须等待服务创建完成,这可能需要一分钟时间

  7. 创建服务实例后,门户中将显示一条通知。

    Screenshot of the deployment succeeded notification.

  8. 暂时无需关注资源,请直接转到下一章。

第 2 章 - Azure 门户:创建媒体服务

若要使用 Azure 媒体服务,需要配置该服务的实例供应用程序使用(其中的帐户持有者必须是管理员)。

  1. 在 Azure 门户中,单击左上角的“创建资源”,搜索“媒体服务”,然后按 Enter。 所需的资源当前带有一个粉红色图标;单击此图标以显示新页面。

    Screenshot of the Azure Portal. The Media Services option is highlighted.

  2. 新页面将提供媒体服务的说明。 在此提示的左下角,单击“创建”按钮以创建与此服务的关联

    Screenshot of the Azure Portal. The Create button is highlighted.

  3. 单击“创建”后将显示一个面板,需要在其中提供有关新媒体服务的一些详细信息

    1. 为该服务实例插入所需的帐户名称

    2. 选择一个“订阅” 。

    3. 选择一个资源组或创建一个新资源组。 通过资源组,可监视和预配 Azure 资产集合、控制其访问权限并管理其计费。 建议保留与单个项目(例如通用资源组下的这些实验室)相关联的所有 Azure 服务。

    若要详细了解 Azure 资源组,请单击此链接了解如何管理 Azure 资源组

    1. 为资源组确定位置(如果正在创建新的资源组)。 理想情况下,此位置在运行应用程序的区域中。 某些 Azure 资产仅在特定区域可用。

    2. 对于“存储帐户”部分,请单击“请选择...”部分,然后单击在上一章中创建的存储帐户

    3. 还需要确认了解应用于此服务的条款和条件。

    4. 单击 “创建”

      Screenshot of the Create Media Service Account page.

  4. 单击“创建”后,必须等待服务创建完成,这可能需要一分钟时间

  5. 创建服务实例后,门户中将显示一条通知。

    Screenshot of the notification icon in the portal menu.

  6. 单击通知可浏览新的服务实例。

    Screenshot of the notification for successful deployment.

  7. 单击通知中的“转到资源”按钮,浏览新的服务实例

  8. 在新媒体服务页的左侧面板中,单击位于下半部分大致中间位置的“资产”链接

  9. 在下一页的左上角,单击“上传”

    Screenshot of the Assets page. Upload and Assets options are highlighted.

  10. 单击“文件夹”图标以浏览文件,并选择要流式传输的第一个 360 度视频

    可以单击此链接下载示例视频

    Screenshot of the upload a video asset page.

警告

长文件名可能会导致编码器出现问题:因此,为确保视频不出问题,请考虑缩短视频文件名的长度。

  1. 视频上传完成后,进度栏会变成绿色。

    Screenshot of the upload a video asset progress bar.

  2. 单击上面的文本(<你的服务名称> -“资产”)返回“资产”页

  3. 可以看到,你的视频已成功上传。 单击该磁贴。

    Screenshot of the Assets page. Video 1 dot M P 4 is highlighted.

  4. 重定向到的页面将显示有关该视频的详细信息。 若要使用该视频,需要单击页面左上角的“编码”按钮对其进行编码

    Screenshot of the asset page. The encode button is highlighted.

  5. 右侧将显示一个新面板,可在其中设置文件的编码选项。 设置以下属性(默认已设置了一些属性):

    1. 媒体编码器名称:媒体编码器标准版

    2. 编码预设:内容自适应多比特率 MP4

    3. 作业名称:使用媒体编码器标准版处理 Video1.mp4

    4. 输出媒体资产名称:Video1.mp4 -- 媒体编码器标准版已编码

      Screenshot of the encode an asset page.

  6. 单击“创建” 按钮。

  7. 你将看到一个添加了编码作业的栏,请单击该栏,随后将出现一个面板,其中显示了编码进度

    Screenshot of the notice bar labeled encoding job added.

    Screenshot of the encoder processing page.

  8. 等待作业完成。 完成后,可以单击该面板右上角的“X”将其关闭。

    Screenshot of the progress bar with the status finished.

    Screenshot of the top menu of the media coder processing page.

    重要

    此操作所需的时间取决于视频的文件大小。 整个过程可能需要相当长的时间。

  9. 创建视频的编码版本后,接下来可将其发布,使其可供访问。 为此,请单击“资产”蓝色链接返回“资产”页

    Screenshot of the Azure Portal. The assets link is highlighted.

  10. 你将看到你的视频,以及资产类型为“多比特率 MP4”的另一个视频

    Screenshot of the Microsoft Azure assets menu.

    注意

    你可能发现,与初始视频一起显示的新资产是“未知”的,其大小为“0”字节,对于这种情况,只需刷新窗口,使该资产更新即可

  11. 单击此新资产。

    Screenshot of the directory listing assets.

  12. 你将看到一个与前面所用面板类似的面板,只不是此面板是一个不同的资产。 单击位于页面顶部中间的“发布”按钮

    Screenshot of the top menu bar. The Publish button is highlighted.

  13. 系统会提示你设置一个定位符,即资产中的文件的入口点。 为方案设置以下属性:

    1. 定位符类型 > 渐进式

    2. 对于日期和时间,系统将设置为从当前日期到未来某个时间(在本例中为一百年)。 请保留现有设置,或根据需要进行更改。

    注意

    有关定位符的详细信息以及可以选择的定位符,请访问 Azure 媒体服务文档

  14. 在该面板的底部,单击“添加”按钮

    Screenshot showing directory listings with the asset to publish dialog.

  15. 视频现已发布,可以使用其终结点进行流式传输。 页面中再往下显示的是“文件”部分。 视频的不同编码版本显示在此部分。 选择最高可能分辨率(下图中为 1920x960 文件),然后右侧会显示一个面板。 该面板中会显示“下载 URL”。 请复制此终结点,因为稍后要在代码中用到

    Screenshot of the Microsoft Azure Files section.

    Screenshot of the asset information page.

    注意

    还可以按“播放”按钮播放视频并对其进行测试

  16. 现在需要上传将在本实验中使用的第二个视频。 按照上述步骤操作,对第二个视频重复相同的过程。 确保同时复制第二个终结点使用以下链接下载第二个视频

  17. 发布这两个视频后,便可以继续学习下一章了。

第 3 章 - 设置 Unity 项目

下面是用于使用混合现实进行开发的典型设置,因此对其他项目来说,这是一个不错的模板。

  1. 打开 Unity,单击“新建”

    Screenshot of Unity projects tab. The New button is highlighted.

  2. 现在需要提供 Unity 项目名称,请插入“MR_360VideoStreaming”。 确保将项目类型设置为“3D”。 将“位置”设置为适合你的位置(请记住,越接近根目录越好)。 然后,单击“创建项目”

    Screenshot of the Unity new projects page.

  3. 在 Unity 处于打开状态时,最好是检查默认的“脚本编辑器”是否设置为“Visual Studio”。转到“编辑”>“首选项”,然后从新窗口导航到“外部工具”。 将外部脚本编辑器更改为 Visual Studio 2017。 关闭“首选项”窗口。

    Screenshot of the external script editor menu. Visual Studio 2017 is selected.

  4. 接下来,转到“文件”“生成设置”,并通过单击“切换平台”按钮将平台切换到“通用 Windows 平台”

  5. 此外,确保:

    1. 将“目标设备”设置为“任何设备”

    2. 将“生成类型”设置为“D3D”

    3. 将“SDK”设置为“最新安装的版本”

    4. 将“Visual Studio 版本”设置为“最新安装的版本”

    5. 将“生成并运行”设置为“本地计算机”

    6. 暂时不用考虑场景设置,因为稍后会设置场景

    7. 其余设置暂时应保留默认值。

      Screenshot of the Unity build settings screen.

  6. 在“生成设置”窗口中,单击“播放器设置”按钮,这会在检查器所在的空间中打开相关面板

  7. 在此面板中,需要验证一些设置:

    1. 在“其他设置”选项卡中

      1. “脚本运行时版本”应为“稳定”(.NET 3.5 等效版本)

      2. “脚本编写后端”应为“.NET”

      3. “API 兼容性级别”应为“.NET 4.6”

        Screenshot showing the Settings for Universal Windows Platform page.

    2. 在面板再靠下部分,在“发布设置”下的“XR 设置”中,勾选“支持虚拟现实”,确保已添加“Windows Mixed Reality SDK”

      Screenshot of the Unity X R settings screen.

    3. 在“发布设置”选项卡的“功能”下,检查以下内容

      • InternetClient

        Screenshot of the Capabilities screen. Internet Client is checked.

  8. 做出这些更改后,关闭“生成设置”窗口

  9. 保存项目:“文件”>“保存项目”

第 4 章 - 导入 InsideOutSphere Unity 包

重要

如果想要跳过本课程的“Unity 设置”部分,直接学习代码,可下载此 .unitypackage,将其作为自定义包导入到项目中,然后从第 5 章继续学习。 仍然需要创建一个 Unity 项目。

对于本课程,需要下载名为 InsideOutSphere.unitypackage 的 Unity 资产包

如何导入 unitypackage

  1. 在面前的 Unity 仪表板中,单击屏幕顶部菜单中的“资产”,然后单击“导入包”>“自定义包”

    Screenshot of the assets menu. The import package menu is open. Custom Package is selected.

  2. 使用文件选择器选择“InsideOutSphere.unitypackage”包,然后单击“打开”。 此时会显示此资产的组件列表。 单击“导入”以确认导入

    Screenshot of the Import Unity Package screen.

  3. 完成导入后,你会看到“Materials”、“Models”和“Prefabs”这三个新文件夹已添加到“Assets”文件夹中。 这是 Unity 项目的典型文件夹结构。

    Screenshot of the assets folder.

    1. 打开“Models”文件夹,你会看到“InsideOutSphere”模型已导入

    2. 在“Materials”文件夹中,你会看到“InsideOutSpheres”材料“lambert1”,以及 GazeButton(很快就会看到它)使用的名为“ButtonMaterial”的材料

    3. “Prefabs”文件夹包含“InsideOutSphere”预制件,其中包含“InsideOutSphere”模型和“GazeButton”

    4. 未包含任何代码,你将按照本课程编写代码

  4. 在“层次结构”中选择“主相机”对象,并更新以下组件

    1. 转换

      1. 位置 = X:0,Y:0,Z:0

      2. 旋转 = X:0,Y:0,Z:0

      3. 缩放 = X:1,Y:1,Z:1

    2. Camera

      1. 清除标志:纯色

      2. 剪裁平面:近:0.1,远:6

        Screenshot of the Inspector screen.

  5. 导航到“Prefab”文件夹,然后将“InsideOutSphere”预制件拖放到“层次结构”面板中

    Screenshot of the Prefab folder menu and the developer environment.

  6. 在“层次结构”中,单击“InsideOutSphere”对象旁边的小箭头将其展开。 你将在其下方看到一个名为“GazeButton”的子对象。 此对象用于更改场景和视频。

    Screenshot of the hierarchy tab.

  7. 在“检查器”窗口中,单击“InsideOutSphere”的 Transform 组件,确保设置了以下属性

变换 - 位置

X Y Z
0 0 0

变换 - 旋转

X Y Z
0 50- 0

变换 - 缩放

X Y Z
0 0 0

Screenshot of the Inspector screen open for Inside Out Sphere.

  1. 单击“GazeButton”子对象,并按如下所示设置其变换

变换 - 位置

X Y Z
3.6 1.3 0

变换 - 旋转

X Y Z
0 0 0

变换 - 缩放

X Y Z
1 1 1

Screenshot of the scene tab open.

第 5 章 - 创建 VideoController 类

VideoController 类承载用于从 Azure 媒体服务流式传输内容的两个视频终结点

若要创建此类,请执行以下操作:

  1. 右键单击“项目”面板中的资产文件夹,然后单击“创建”>“文件夹”。 将文件夹命名为“脚本”

    Screenshot of the asset folder menu. The create menu is open and folder is selected.

    Screenshot of the project tab. The Assets folder is selected.

  2. 双击“Scripts”文件夹将其打开

  3. 右键单击该文件夹,然后单击“创建”>“C# 脚本”。 将脚本命名为“VideoController”

    Screenshot of the file named Video Controller.

  4. 双击新的“VideoController”脚本以在 Visual Studio 2017 中将其打开

    Screenshot of the code for the Video Controller file.

  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 版本 2017.4.1f1 中使用 https 时会出现一个已知问题。 如果视频在播放时出错,请尝试改用“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. 返回到 Unity 之前,请在 Visual Studio 中“保存所做的更改”。

  12. 返回 Unity 编辑器,单击“Scripts”文件夹中[from]{.underline}的“VideoController”类,并将其拖放到“层次结构”面板中的“主相机”对象

  13. 单击“主相机”并查看“检查器”面板。 你会发现,在新添加的 Script 组件中,有一个包含空值的字段。 这是一个引用字段,其目标是代码中的公共变量。

  14. 将“InsideOutSphere”对象从“层次结构”面板拖放到“球体”槽,如下图所示

    Screenshot of the hierarchy menu. Main Camera is selected.Screenshot of the Sphere slot.

第 6 章 - 创建 Gaze 类

此类负责创建从主相机正向投影的光线投射,以检测用户正在注视的对象。 在这种情况下,光线投射需要识别用户是否正在场景中注视 GazeButton 对象并触发行为

若要创建此类,请执行以下操作:

  1. 转到之前创建的“脚本”文件夹

  2. 在“项目面板”中右键单击并选择“创建”>“C# 脚本”。 将脚本命名为“Gaze”

  3. 双击新的“Gaze”脚本以在 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() 方法中添加以下代码,以投影光线投射并检测目标命中

        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. 返回到 Unity 之前,请在 Visual Studio 中“保存所做的更改”。

  9. 单击 Scripts 文件夹中的“Gaze”类,并将其拖放到“层次结构”面板中的“主相机”对象

第 7 章 - 设置两个 Unity 场景

本章的目的是设置两个场景,每个场景承载要流式传输的视频。 你将复制已创建的场景,这样就不需要再次设置场景,不过,随后需要编辑新场景,使 GazeButton 对象位于不同位置并具有不同的外观。 这样做是为了展示如何在场景之间切换。

  1. 为此,请转到“文件”>“场景另存为...”。此时将出现一个“保存”窗口。 单击“新建文件夹”按钮

    Chapter 7 - Setup the two Unity Scenes

  2. 将文件夹命名为“Scenes”

  3. “保存场景”窗口仍保持打开状态。 打开新建的“Scenes”文件夹

  4. 在“文件名:”文本字段中键入“VideoScene1”,然后按“保存”

  5. 返回 Unity,打开“Scenes”文件夹,然后单击“VideoScene1”文件。 在键盘上按 Ctrl + D 复制该场景

    提示

    也可以通过导航到“编辑”>“复制”来执行“复制”命令

  6. Unity 将自动递增场景名称编号,但仍需检查该名称,以确保它与先前插入的代码匹配。

    应有 VideoScene1 和 VideoScene2 这两个文件

  7. 在两个场景中,转到“文件”>“生成设置”。 打开“生成设置”窗口后,将场景拖放到“生成中的场景”部分

    Screenshot of the Build Settings window.

    提示

    可以通过按住 Ctrl 按钮并单击每个场景来从“Scenes”文件夹中选择两个场景,最后拖放这两个场景

  8. 关闭“生成设置”窗口,然后双击“VideoScene2”

  9. 打开第二个场景后,单击“InsideOutSphere”的“GazeButton”子对象,并按如下所示设置其变换

变换 - 位置

X Y Z
0 1.3 3.6

变换 - 旋转

X Y Z
0 0 0

变换 - 缩放

X Y Z
1 1 1
  1. 在“GazeButton”子对象仍处于选中状态的情况下,查看“检查器”和“网格筛选器”。 单击“网格”参考字段旁边的小目标

    Screenshot of the inspector screen for Gaze Button.

  2. 此时会出现“选择网格”弹出窗口。 在“资产”列表中双击“立方体”网格

    Screenshot of the Select Mesh popup window.

  3. “网格筛选器”将会更新,现在是一个立方体。 现在,单击“球体碰撞体”旁边的齿轮图标,然后单击“删除组件”以从此对象中删除碰撞体

    Screenshot of the Sphere Collider menu. Remove component is selected.

  4. 在“GazeButton”仍处于选中状态的情况下,单击“检查器”底部的“添加组件”按钮。 在搜索字段中键入“盒”,“盒碰撞体”将成为一个选项 -- 单击该选项,将盒碰撞体添加到“GazeButton”对象

    Screenshot of the Add Component search box.

  5. GazeButton 现已部分更新,其外观有所不同,但是,现在你需要创建一个新材料,使该对象的外观完全不同,并且更容易识别为不同的对象,而不是第一个场景中的对象

  6. 在“项目”面板中导航到“Materials”文件夹。 复制“ButtonMaterial”材料(在键盘上按 Ctrl + D,或者左键单击“材料”,然后从“编辑”文件菜单选项中选择“复制”)

    Screenshot of the Materials folder in the project tab.Screenshot of the edit menu with duplicate selected.

  7. 选择新的“ButtonMaterial”材料(此处命名为“ButtonMaterial 1”),然后在“检查器”中单击“反照率”颜色窗口。 此时将出现一个弹出窗口,可在其中选择另一种颜色(选择喜欢的颜色),然后关闭该弹出窗口。 “材料”是其自身的实例,不同于原始实例。

    Screenshot of the color selection popup.

  8. 将新材料拖放到“GazeButton”子对象,现在可以完全更新其外观,以便轻松将其与第一个场景按钮区分开来

    Screenshot of the project editor scene tab.

  9. 现在,可以在生成 UWP 项目之前先在编辑器中测试项目。

    • 在“编辑器”中按“播放”按钮,并戴上头戴显示设备

      Screenshot showing the play, pause, and skip buttons. The play button is highlighted.

  10. 注视两个“GazeButton”对象以在第一个和第二个视频之间切换

第 8 章 - 生成 UWP 解决方案

确认编辑器中未出现错误后,便可以开始生成了。

若要生成,请执行以下操作:

  1. 单击“文件”>“保存”,保存当前场景

  2. 选中名为“Unity C# 项目”的框(此操作很重要,因为这样可以在生成完成后编辑类)

  3. 转到“文件”>“生成设置”,单击“生成”

  4. 系统将提示你选择要在其中生成解决方案的文件夹。

  5. 创建“BUILDS”文件夹,然后在此文件夹中使用适当的名称创建另一个文件夹

  6. 单击新文件夹,然后单击“选择文件夹”,以选择该文件夹在该位置开始生成

    Screenshot of the BUILDS folder highlighted.Screenshot of the Video Streaming Build folder highlighted.

  7. Unity 完成生成后(可能需要一段时间),它将在生成位置打开“文件资源管理器”窗口

第 9 章 - 在本地计算机上部署

生成完成后,“文件资源管理器”窗口将显示在生成位置。 打开要在其中生成的命名文件夹,然后双击该文件夹中的解决方案 (.sln) 文件,以在 Visual Studio 2017 中打开解决方案。

剩下的操作就是将应用部署到你的计算机(或本地计算机)

若要部署到本地计算机,请执行以下操作:

  1. 在 Visual Studio 2017 中,打开刚刚创建的解决方案文件

  2. 在“解决方案平台”中,选择“x86,本地计算机”

  3. 在“解决方案配置”中,选择“调试”

    Screenshot of the Solution Configuration menu.

  4. 现在需要还原解决方案的所有包。 右键单击你的解决方案,然后单击“还原解决方案的 NuGet 包...”

    注意

    这样做是因为需要将 Unity 生成的包指定为目标才能与本地计算机引用配合使用。

  5. 转到“生成”菜单,并单击“部署解决方案”,将应用程序旁加载到计算机。 Visual Studio 将生成再部署应用程序。

  6. 应用现在应显示在已安装的应用列表中,随时可以启动。

    Screenshot of the list of installed apps.

运行混合现实应用程序时,你将置身于应用中使用的 InsideOutSphere 模型内。 此球体是视频将流式传输到的位置,提供传入视频的 360 度视图(是按照这种视角拍摄的)。 如果加载视频需要几秒钟时间,请不要感到惊讶,因为应用受 Internet 速度的影响,而视频需要先提取再下载,然后再流式传输到应用。 准备就绪后,通过凝视红色球体来更改场景并打开第二个视频! 然后随时返回,使用第二个场景中的蓝色立方体!

完成的 Azure 媒体服务应用程序

祝贺你,现已生成了一个利用 Azure 媒体服务来流式传输 360 度视频的混合现实应用。

Screenshot of an example mixed reality app.

Screenshot of a mixed reality app example.

额外练习

练习 1

在本教程中,完全可以仅使用一个场景来更改视频。 请在应用程序中试验并将其整合到单个场景中! 甚至可以在混合场景中添加另一个视频。

练习 2

体验 Azure 和 Unity,并尝试实现让应用根据 Internet 连接强度自动选择具有不同文件大小的视频的功能。