HoloLens(第一代)输入 210:凝视

重要

混合现实学院教程在制作时考虑到了 HoloLens(第一代)、Unity 2017 和混合现实沉浸式头戴显示设备。 因此,对于仍在寻求这些设备的开发指导的开发人员而言,我们觉得很有必要保留这些教程。 我们不会在这些教程中更新 HoloLens 2 所用的最新工具集或交互相关的内容,因此这些教程可能与较新版本的 Unity 不相符。 我们将维护这些教程,使之持续适用于支持的设备。 已经为 HoloLens 2 发布了一系列新教程

凝视是第一种形式的输入,它反映用户的意图和感知。 MR 输入 210(也称为项目资源管理器)深入探讨了 Windows Mixed Reality 的凝视相关概念。 我们会将上下文感知添加到光标和全息影像,并充分利用应用对用户凝视的了解。

我们安排了一位友好的宇航员来帮助你学习凝视的概念。 在 MR 基础知识 101 中,有一个简单的光标可以跟随视线。 今天,我们将在简单光标的基础上更进一步:

  • 使光标和全息影像具有凝视感知能力:两者都将根据用户正在注视的位置或用户未注视的位置而变化。 这样,它们便能够感知上下文。
  • 我们将向光标和全息影像添加反馈,以便为用户提供有关目标对象的更多上下文。 这种反馈可以是音频和视觉反馈。
  • 我们将介绍定位方法,帮助用户命中较小的目标。
  • 我们将介绍如何使用方向指示器,将用户的注意力吸引到你的全息影像上。
  • 我们会讲解一些技术,当用户在你的世界中移动时,让你的全息影像与用户一起移动。

重要

下面每一章中嵌入的视频是使用旧版 Unity 和混合现实工具包录制的。 虽然分步说明比较准确且是最新的,但你在相应视频中可能会看到已过时的脚本和视觉效果。 保留这些视频是为了供后来的读者参考,并且涉及的概念现在仍然适用。

设备支持

课程 HoloLens 沉浸式头戴显示设备
MR 输入 210:凝视

开始之前

先决条件

项目文件

  • 下载项目所需的文件。 需要 Unity 2017.2 或更高版本。
  • 将文件解压缩到桌面或其他易于访问的位置。

注意

如果要在下载源代码之前查看它,可以在 GitHub 上查看

勘误表和备注

  • 在 Visual Studio 中,需要在“工具”->“选项”->“调试”下禁用(取消选中)“仅我的代码”,以便在代码中命中断点。

第 1 章 - Unity 设置

目标

  • 针对 Hololens 开发优化 Unity。
  • 导入资产并设置场景。
  • 在 HoloLens 中查看宇航员。

说明

  1. 启动 “Unity”。
  2. 选择“新建项目”
  3. 将项目命名为 ModelExplorer
  4. 输入先前解压缩的 Gaze 文件夹所在的位置
  5. 请确保将项目设置为“3D”
  6. 单击“创建项目”。

HoloLens 的 Unity 设置

需要让 Unity 知道我们尝试导出的应用应该创建沉浸式视图而不是 2D 视图。 为此,请将 HoloLens 添加为虚拟现实设备。

  1. 转到“编辑”>“项目设置”>“播放器”
  2. 在检查器面板中,对于“播放器设置”,请选择“Windows Store”图标
  3. 展开“XR 设置”组
  4. 在“呈现”部分,选中“支持虚拟现实”复选框,添加新“虚拟现实 SDK 的”列表
  5. 验证列表中是否显示“Windows 混合现实”。 如果未显示,请在列表底部选择 + 按钮,然后选择“Windows Holographic”

接下来,需要将脚本后端设置为 .NET。

  1. 转到“编辑”>“项目设置”>“播放器”(完成上一步骤后你可能尚未关闭此对话框)
  2. 在检查器面板中,对于“播放器设置”,请选择“Windows Store”图标
  3. 在“其他设置”配置部分,确保“脚本后端”设置为“.NET”

最后,更新质量设置,以便在 HoloLens 上实现高性能。

  1. 转到“编辑”>“项目设置”>“质量”
  2. 单击 Windows Store 图标下“默认”行中的向下箭头
  3. 对于“Windows Store 应用”,请选择“极低”

导入项目资产

  1. 在“项目”面板中右键单击“Assets”文件夹
  2. 单击“导入包”>“自定义包”
  3. 导航到下载的项目文件,然后单击“ModelExplorer.unitypackage”
  4. 单击“打开”。
  5. 加载包后,单击“导入”按钮

设置场景

  1. 在“层次结构”中,删除“主照相机”
  2. 在“HoloToolkit”文件夹中,打开“Input”文件夹,然后打开“Prefabs”文件夹
  3. 将“MixedRealityCameraParent”预制件从“Prefabs”文件夹拖放到“层次结构”中
  4. 在“层次结构”中右键单击“定向光源”,然后选择“删除”
  5. 在“Holograms”文件夹中,将以下资源拖放到“层次结构”的根目录中
    • AstroMan
    • 光线
    • SpaceAudioSource
    • SpaceBackground
  6. 启动“播放模式”▶ 查看宇航员
  7. 再次单击“播放模式”▶ 以停止
  8. 在“Holograms”文件夹中,找到“Fitbox”资产并将其拖放到“层次结构”的根目录中
  9. 在“层次结构”面板中选择“Fitbox”
  10. 将“AstroMan”集合从“层次结构”拖放到“检查器”面板中 Fitbox 的“全息影像集合”属性

保存项目

  1. 保存新场景:“文件”>“将场景另存为”
  2. 单击“新建文件夹”并将文件夹命名为“Scenes”
  3. 将文件命名为“ModelExplorer”,并将其保存到“Scenes”文件夹中

生成项目

  1. 在 Unity 中,选择“文件”>“生成设置”
  2. 单击“添加开放式场景”以添加场景
  3. 在“平台”列表中选择“通用 Windows 平台”,然后单击“切换平台”
  4. 如果专门针对 HoloLens 进行开发,请将“目标设备”设置为“HoloLens”。 否则,请将此选项保留为“任何设备”
  5. 确保将“生成类型”设置为“D3D”,将“SDK”设置为“最新安装版本”(应该是 SDK 16299 或更高版本)
  6. 单击“生成”
  7. 创建名为“App”的新文件夹
  8. 单击“App”文件夹
  9. 按“选择文件夹”

完成 Unity 设置后,将出现一个文件资源管理器窗口。

  1. 打开“App”文件夹。
  2. 打开“ModelExplorer Visual Studio 解决方案”

如果是部署到 HoloLens:

  1. 使用 Visual Studio 中的顶部工具栏,将目标从“调试”更改为“发布”,并从“ARM”更改为“x86”
  2. 单击“本地计算机”按钮旁边的下拉箭头,然后选择“远程计算机”
  3. 输入 HoloLens 设备 IP 地址,将“身份验证模式”设置为“通用(未加密协议)”。 单击“选择”。 如果你不知道自己的设备 IP 地址,可以在“设置”>“网络和 Internet”>“高级选项”中找到。
  4. 在顶部菜单栏中,单击“调试”->“开始执行(不调试)”或按 Ctrl + F5。 如果这是你第一次部署到设备,需要将设备与 Visual Studio 配对
  5. 部署应用后,使用“选择手势”关闭“工具箱”

如果部署到沉浸式头戴显示设备:

  1. 使用 Visual Studio 中的顶部工具栏,将目标从“调试”更改为“发布”,并从“ARM”更改为“x64”
  2. 确保部署目标设置为“本地计算机”
  3. 在顶部菜单栏中,单击“调试”->“开始执行(不调试)”或按 Ctrl + F5
  4. 部署应用后,通过拉动运动控制器上的触发器来关闭“工具箱”

第 2 章 - 光标和目标反馈

目标

  • 光标视觉设计和行为。
  • 基于凝视的光标反馈。
  • 基于凝视的全息影像反馈。

我们将根据一些光标设计原则开展工作,即:

  • 光标始终存在。
  • 不要让光标变得太小或太大。
  • 避免遮挡内容。

说明

  1. 在“HoloToolkit\Input\Prefabs”文件夹中,找到“InputManager”资产
  2. 将“InputManager”拖放到“层次结构”中
  3. 在“HoloToolkit\Input\Prefabs”文件夹中,找到“Cursor”资产
  4. 将“Cursor”拖放到“层次结构”中
  5. 在“层次结构”中选择“InputManager”对象
  6. 将“Cursor”对象从“层次结构”拖放到 InputManager 的“SimpleSinglePointerSelector”的“Cursor”字段中(位于“检查器”底部)

Simple Single Pointer Selector set-up

生成和部署

  1. 选择“文件”>“生成设置”以重新生成应用
  2. 打开“App”文件夹。
  3. 打开“ModelExplorer Visual Studio 解决方案”
  4. 单击“调试”>“开始执行(不调试)”或按 Ctrl+F5
  5. 观察光标是如何绘制的,以及它在接触全息影像时如何改变外观。

说明

  1. 在“层次结构”面板中,展开“AstroMan”->“GEO_G”->“Back_Center”对象
  2. 双击“Interactible.cs”,在 Visual Studio 中打开它
  3. 取消注释“Interactible.cs”中“IFocusable.OnFocusEnter()”和“IFocusable.OnFocusExit()”回调中的行。 当焦点(通过凝视或控制器指向)进入和退出特定 GameObject 的碰撞体时,混合现实工具包的 InputManager 会调用这些行。
/* TODO: DEVELOPER CODING EXERCISE 2.d */

void IFocusable.OnFocusEnter()
{
    for (int i = 0; i < defaultMaterials.Length; i++)
    {
        // 2.d: Uncomment the below line to highlight the material when gaze enters.
        defaultMaterials[i].EnableKeyword("_ENVIRONMENT_COLORING");
    }
}

void IFocusable.OnFocusExit()
{
    for (int i = 0; i < defaultMaterials.Length; i++)
    {
        // 2.d: Uncomment the below line to remove highlight on material when gaze exits.
        defaultMaterials[i].DisableKeyword("_ENVIRONMENT_COLORING");
    }
}

注意

我们使用上面的 EnableKeywordDisableKeyword。 若要在你自己的应用中结合工具包的标准着色器使用它们,需要遵循通过脚本访问材料的 Unity 指导原则。 在本例中,我们已在 Resources 文件夹中包含了所需的突出显示材料的三种变体(查找名称中包含 highlight 的三种材料)。

生成和部署

  1. 与前面一样,生成项目并部署到 HoloLens。
  2. 观察当视线瞄准某个对象时会发生什么,未瞄准某个对象时又会发生什么。

第 3 章 - 定位方法

目标

  • 更轻松地定位全息影像。
  • 使头部运动保持自然稳定。

说明

  1. 在“层次结构”面板中,选择“InputManager”对象
  2. 在“检查器”面板中,找到“Gaze Stabilizer”脚本。 如果想要查看该脚本,请单击它以在 Visual Studio 中打开。
    • 此脚本迭代光线投射数据样本,并帮助稳定用户的视线以实现精确定位。
  3. 在“检查器”中,可以编辑“存储的稳定性样本”值。 此值表示稳定器迭代的以计算稳定值的样本数。

第 4 章 - 方向指示器

目标

  • 在光标上添加方向指示器以帮助查找全息影像。

说明

我们将使用 DirectionIndicator.cs 文件来实现以下目的

  1. 如果用户未凝视全息影像,则显示方向指示器。
  2. 如果用户凝视全息影像,则隐藏方向指示器。
  3. 更新方向指示器以指向全息影像。

现在就开始吧。

  1. 在“层次结构”面板中单击“AstroMan”对象,然后单击箭头将其展开
  2. 在“层次结构”面板中,选择“AstroMan”下的“DirectionalIndicator”对象
  3. 在“检查器”面板中,单击“添加组件”按钮
  4. 在菜单中的搜索框内键入“方向指示器”。 选择搜索结果。
  5. 在“层次结构”面板中,将“Cursor”对象拖放到“检查器”中的“光标”属性上
  6. 在“项目”面板中的“Holograms”文件夹内,将“DirectionalIndicator”资产拖放到“检查器”中的“方向指示器”属性上
  7. 构建并部署应用。
  8. 观看方向指示器对象如何帮助你找到宇航员。

第 5 章 - 标牌

目标

  • 使用标牌使全息影像始终面向你。

我们将使用 Billboard.cs 文件来使 GameObject 始终面向用户

  1. 在“层次结构”面板中,选择“AstroMan”对象
  2. 在“检查器”面板中,单击“添加组件”按钮
  3. 在菜单中的搜索框内键入“标牌”。 选择搜索结果。
  4. 在“检查器”中,将“枢轴”设置为“Y”
  5. 试试看! 像前面一样生成并部署应用。
  6. 将会看到,无论如何更改视点,标牌对象都始终会面向你。
  7. 暂时从“AstroMan”中删除脚本

第 6 章 - 跟随

目标

  • 使用“跟随”方法让全息影像在房间中跟随我们。

处理此问题时需要遵循以下设计约束:

  • 内容应始终一目了然。
  • 内容未被遮挡。
  • 头部锁定内容会让人不适。

此处的解决方法是使用“跟随”方法。

跟随对象永远不会完全离开用户的视野。 可将跟随视为通过橡皮筋固定在用户头部的对象。 当用户运动时,内容将朝向视野边缘滑动而不会完全消失,从而很容易看到。 当用户凝视尾随对象时,该对象会更完整地进入视野。

我们将使用 SimpleTagalong.cs 文件来实现以下目的

  1. 确定跟随对象是否在照相机边界范围内。
  2. 如果不在视锥范围内,请将跟随对象的一部分定位在视锥范围内。
  3. 否则,将跟随对象定位到默认的用户距离。

为此,必须先更改 Interactible.cs 脚本以调用 TagalongAction

  1. 完成编程练习 6.a 来了解如何编辑 Interactible.cs(取消注释 84 到 87 行)
/* TODO: DEVELOPER CODING EXERCISE 6.a */
// 6.a: Uncomment the lines below to perform a Tagalong action.
if (interactibleAction != null)
{
    interactibleAction.PerformAction();
}

点击全息影像时,InteractibleAction.cs 脚本将搭配 Interactible.cs 来执行自定义操作。 在本例中,我们专门使用一个跟随对象。

  • 在“Scripts”文件夹中,单击“TagalongAction.cs”资产以在 Visual Studio 中打开
  • 完成编程练习或将其更改为:
    • 在“层次结构”顶部的搜索栏中键入“ChestButton_Center”并选择结果
    • 在“检查器”面板中,单击“添加组件”按钮
    • 在菜单中的搜索框内键入“Tagalong Action”。 选择搜索结果。
    • 在“Holograms”文件夹中找到“Tagalong”资产
    • 在“层次结构”中选择“ChestButton_Center”对象。 将“TagAlong”对象从“项目”面板拖放到“检查器”中的“要跟随的对象”属性上
    • 将“Tagalong Action”对象从“检查器”拖放到“Interactible”脚本的“Interactible Action”字段中
  • 双击“TagalongAction”脚本以在 Visual Studio 中打开它

Interactible set-up

需要添加以下各项:

  • 将功能添加到 TagalongAction 脚本中的 PerformAction 函数(继承自 InteractibleAction)。
  • 将标牌添加到凝视的对象,将枢轴设置为 XY。
  • 然后在对象中添加简单跟随。

这就是我们在 TagalongAction.cs 中的解决方案

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using HoloToolkit.Unity;
using UnityEngine;

public class TagalongAction : InteractibleAction
{
    [SerializeField]
    [Tooltip("Drag the Tagalong prefab asset you want to display.")]
    private GameObject objectToTagalong;

    private void Awake()
    {
        if (objectToTagalong != null)
        {
            objectToTagalong = Instantiate(objectToTagalong);
            objectToTagalong.SetActive(false);

            /* TODO: DEVELOPER CODING EXERCISE 6.b */

            // 6.b: AddComponent Billboard to objectToTagAlong,
            // so it's always facing the user as they move.
            Billboard billboard = objectToTagalong.AddComponent<Billboard>();

            // 6.b: AddComponent SimpleTagalong to objectToTagAlong,
            // so it's always following the user as they move.
            objectToTagalong.AddComponent<SimpleTagalong>();

            // 6.b: Set any public properties you wish to experiment with.
            billboard.PivotAxis = PivotAxis.XY; // Already the default, but provided in case you want to edit
        }
    }

    public override void PerformAction()
    {
        // Recommend having only one tagalong.
        if (objectToTagalong == null || objectToTagalong.activeSelf)
        {
            return;
        }

        objectToTagalong.SetActive(true);
    }
}
  • 试试看! 构建并部署应用。
  • 观察内容如何跟随凝视点的中心移动,但不是连续跟随且不会阻挡它。