HoloLens(第一代)输入 210:凝视
重要
混合现实学院教程在制作时考虑到了 HoloLens(第一代)、Unity 2017 和混合现实沉浸式头戴显示设备。 因此,对于仍在寻求这些设备的开发指导的开发人员而言,我们觉得很有必要保留这些教程。 我们不会在这些教程中更新 HoloLens 2 所用的最新工具集或交互相关的内容,因此这些教程可能与较新版本的 Unity 不相符。 我们将维护这些教程,使之持续适用于支持的设备。 已经为 HoloLens 2 发布了一系列新教程。
凝视是第一种形式的输入,它反映用户的意图和感知。 MR 输入 210(也称为项目资源管理器)深入探讨了 Windows Mixed Reality 的凝视相关概念。 我们会将上下文感知添加到光标和全息影像,并充分利用应用对用户凝视的了解。
我们安排了一位友好的宇航员来帮助你学习凝视的概念。 在 MR 基础知识 101 中,有一个简单的光标可以跟随视线。 今天,我们将在简单光标的基础上更进一步:
- 使光标和全息影像具有凝视感知能力:两者都将根据用户正在注视的位置或用户未注视的位置而变化。 这样,它们便能够感知上下文。
- 我们将向光标和全息影像添加反馈,以便为用户提供有关目标对象的更多上下文。 这种反馈可以是音频和视觉反馈。
- 我们将介绍定位方法,帮助用户命中较小的目标。
- 我们将介绍如何使用方向指示器,将用户的注意力吸引到你的全息影像上。
- 我们会讲解一些技术,当用户在你的世界中移动时,让你的全息影像与用户一起移动。
重要
下面每一章中嵌入的视频是使用旧版 Unity 和混合现实工具包录制的。 虽然分步说明比较准确且是最新的,但你在相应视频中可能会看到已过时的脚本和视觉效果。 保留这些视频是为了供后来的读者参考,并且涉及的概念现在仍然适用。
设备支持
课程 | HoloLens | 沉浸式头戴显示设备 |
---|---|---|
MR 输入 210:凝视 | ✔ | ✔ |
开始之前
先决条件
- 一台安装了正确工具的 Windows 10 电脑。
- 基础的 C# 编程能力。
- 应已完成 MR 基础知识 101。
- 一台配置用于开发的 HoloLens 设备。
项目文件
- 下载项目所需的文件。 需要 Unity 2017.2 或更高版本。
- 将文件解压缩到桌面或其他易于访问的位置。
注意
如果要在下载源代码之前查看它,可以在 GitHub 上查看。
勘误表和备注
- 在 Visual Studio 中,需要在“工具”->“选项”->“调试”下禁用(取消选中)“仅我的代码”,以便在代码中命中断点。
第 1 章 - Unity 设置
目标
- 针对 Hololens 开发优化 Unity。
- 导入资产并设置场景。
- 在 HoloLens 中查看宇航员。
说明
- 启动 “Unity”。
- 选择“新建项目”。
- 将项目命名为 ModelExplorer。
- 输入先前解压缩的 Gaze 文件夹所在的位置。
- 请确保将项目设置为“3D”。
- 单击“创建项目”。
HoloLens 的 Unity 设置
需要让 Unity 知道我们尝试导出的应用应该创建沉浸式视图而不是 2D 视图。 为此,请将 HoloLens 添加为虚拟现实设备。
- 转到“编辑”>“项目设置”>“播放器”。
- 在检查器面板中,对于“播放器设置”,请选择“Windows Store”图标。
- 展开“XR 设置”组。
- 在“呈现”部分,选中“支持虚拟现实”复选框,添加新“虚拟现实 SDK 的”列表。
- 验证列表中是否显示“Windows 混合现实”。 如果未显示,请在列表底部选择 + 按钮,然后选择“Windows Holographic”。
接下来,需要将脚本后端设置为 .NET。
- 转到“编辑”>“项目设置”>“播放器”(完成上一步骤后你可能尚未关闭此对话框)。
- 在检查器面板中,对于“播放器设置”,请选择“Windows Store”图标。
- 在“其他设置”配置部分,确保“脚本后端”设置为“.NET”
最后,更新质量设置,以便在 HoloLens 上实现高性能。
- 转到“编辑”>“项目设置”>“质量”。
- 单击 Windows Store 图标下“默认”行中的向下箭头。
- 对于“Windows Store 应用”,请选择“极低”。
导入项目资产
- 在“项目”面板中右键单击“Assets”文件夹。
- 单击“导入包”>“自定义包”。
- 导航到下载的项目文件,然后单击“ModelExplorer.unitypackage”。
- 单击“打开”。
- 加载包后,单击“导入”按钮。
设置场景
- 在“层次结构”中,删除“主照相机”。
- 在“HoloToolkit”文件夹中,打开“Input”文件夹,然后打开“Prefabs”文件夹。
- 将“MixedRealityCameraParent”预制件从“Prefabs”文件夹拖放到“层次结构”中。
- 在“层次结构”中右键单击“定向光源”,然后选择“删除”。
- 在“Holograms”文件夹中,将以下资源拖放到“层次结构”的根目录中:
- AstroMan
- 光线
- SpaceAudioSource
- SpaceBackground
- 启动“播放模式”▶ 查看宇航员。
- 再次单击“播放模式”▶ 以停止。
- 在“Holograms”文件夹中,找到“Fitbox”资产并将其拖放到“层次结构”的根目录中。
- 在“层次结构”面板中选择“Fitbox”。
- 将“AstroMan”集合从“层次结构”拖放到“检查器”面板中 Fitbox 的“全息影像集合”属性。
保存项目
- 保存新场景:“文件”>“将场景另存为”。
- 单击“新建文件夹”并将文件夹命名为“Scenes”。
- 将文件命名为“ModelExplorer”,并将其保存到“Scenes”文件夹中。
生成项目
- 在 Unity 中,选择“文件”>“生成设置”。
- 单击“添加开放式场景”以添加场景。
- 在“平台”列表中选择“通用 Windows 平台”,然后单击“切换平台”。
- 如果专门针对 HoloLens 进行开发,请将“目标设备”设置为“HoloLens”。 否则,请将此选项保留为“任何设备”。
- 确保将“生成类型”设置为“D3D”,将“SDK”设置为“最新安装版本”(应该是 SDK 16299 或更高版本)。
- 单击“生成”。
- 创建名为“App”的新文件夹。
- 单击“App”文件夹。
- 按“选择文件夹”。
完成 Unity 设置后,将出现一个文件资源管理器窗口。
- 打开“App”文件夹。
- 打开“ModelExplorer Visual Studio 解决方案”。
如果是部署到 HoloLens:
- 使用 Visual Studio 中的顶部工具栏,将目标从“调试”更改为“发布”,并从“ARM”更改为“x86”。
- 单击“本地计算机”按钮旁边的下拉箭头,然后选择“远程计算机”。
- 输入 HoloLens 设备 IP 地址,将“身份验证模式”设置为“通用(未加密协议)”。 单击“选择”。 如果你不知道自己的设备 IP 地址,可以在“设置”>“网络和 Internet”>“高级选项”中找到。
- 在顶部菜单栏中,单击“调试”->“开始执行(不调试)”或按 Ctrl + F5。 如果这是你第一次部署到设备,需要将设备与 Visual Studio 配对。
- 部署应用后,使用“选择手势”关闭“工具箱”。
如果部署到沉浸式头戴显示设备:
- 使用 Visual Studio 中的顶部工具栏,将目标从“调试”更改为“发布”,并从“ARM”更改为“x64”。
- 确保部署目标设置为“本地计算机”。
- 在顶部菜单栏中,单击“调试”->“开始执行(不调试)”或按 Ctrl + F5。
- 部署应用后,通过拉动运动控制器上的触发器来关闭“工具箱”。
第 2 章 - 光标和目标反馈
目标
- 光标视觉设计和行为。
- 基于凝视的光标反馈。
- 基于凝视的全息影像反馈。
我们将根据一些光标设计原则开展工作,即:
- 光标始终存在。
- 不要让光标变得太小或太大。
- 避免遮挡内容。
说明
- 在“HoloToolkit\Input\Prefabs”文件夹中,找到“InputManager”资产。
- 将“InputManager”拖放到“层次结构”中。
- 在“HoloToolkit\Input\Prefabs”文件夹中,找到“Cursor”资产。
- 将“Cursor”拖放到“层次结构”中。
- 在“层次结构”中选择“InputManager”对象。
- 将“Cursor”对象从“层次结构”拖放到 InputManager 的“SimpleSinglePointerSelector”的“Cursor”字段中(位于“检查器”底部)。
生成和部署
- 选择“文件”>“生成设置”以重新生成应用。
- 打开“App”文件夹。
- 打开“ModelExplorer Visual Studio 解决方案”。
- 单击“调试”>“开始执行(不调试)”或按 Ctrl+F5。
- 观察光标是如何绘制的,以及它在接触全息影像时如何改变外观。
说明
- 在“层次结构”面板中,展开“AstroMan”->“GEO_G”->“Back_Center”对象。
- 双击“Interactible.cs”,在 Visual Studio 中打开它。
- 取消注释“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");
}
}
注意
我们使用上面的 EnableKeyword
和 DisableKeyword
。 若要在你自己的应用中结合工具包的标准着色器使用它们,需要遵循通过脚本访问材料的 Unity 指导原则。 在本例中,我们已在 Resources 文件夹中包含了所需的突出显示材料的三种变体(查找名称中包含 highlight 的三种材料)。
生成和部署
- 与前面一样,生成项目并部署到 HoloLens。
- 观察当视线瞄准某个对象时会发生什么,未瞄准某个对象时又会发生什么。
第 3 章 - 定位方法
目标
- 更轻松地定位全息影像。
- 使头部运动保持自然稳定。
说明
- 在“层次结构”面板中,选择“InputManager”对象。
- 在“检查器”面板中,找到“Gaze Stabilizer”脚本。 如果想要查看该脚本,请单击它以在 Visual Studio 中打开。
- 此脚本迭代光线投射数据样本,并帮助稳定用户的视线以实现精确定位。
- 在“检查器”中,可以编辑“存储的稳定性样本”值。 此值表示稳定器迭代的以计算稳定值的样本数。
第 4 章 - 方向指示器
目标
- 在光标上添加方向指示器以帮助查找全息影像。
说明
我们将使用 DirectionIndicator.cs 文件来实现以下目的:
- 如果用户未凝视全息影像,则显示方向指示器。
- 如果用户凝视全息影像,则隐藏方向指示器。
- 更新方向指示器以指向全息影像。
现在就开始吧。
- 在“层次结构”面板中单击“AstroMan”对象,然后单击箭头将其展开。
- 在“层次结构”面板中,选择“AstroMan”下的“DirectionalIndicator”对象。
- 在“检查器”面板中,单击“添加组件”按钮。
- 在菜单中的搜索框内键入“方向指示器”。 选择搜索结果。
- 在“层次结构”面板中,将“Cursor”对象拖放到“检查器”中的“光标”属性上。
- 在“项目”面板中的“Holograms”文件夹内,将“DirectionalIndicator”资产拖放到“检查器”中的“方向指示器”属性上。
- 构建并部署应用。
- 观看方向指示器对象如何帮助你找到宇航员。
第 5 章 - 标牌
目标
- 使用标牌使全息影像始终面向你。
我们将使用 Billboard.cs 文件来使 GameObject 始终面向用户。
- 在“层次结构”面板中,选择“AstroMan”对象。
- 在“检查器”面板中,单击“添加组件”按钮。
- 在菜单中的搜索框内键入“标牌”。 选择搜索结果。
- 在“检查器”中,将“枢轴”设置为“Y”。
- 试试看! 像前面一样生成并部署应用。
- 将会看到,无论如何更改视点,标牌对象都始终会面向你。
- 暂时从“AstroMan”中删除脚本。
第 6 章 - 跟随
目标
- 使用“跟随”方法让全息影像在房间中跟随我们。
处理此问题时需要遵循以下设计约束:
- 内容应始终一目了然。
- 内容未被遮挡。
- 头部锁定内容会让人不适。
此处的解决方法是使用“跟随”方法。
跟随对象永远不会完全离开用户的视野。 可将跟随视为通过橡皮筋固定在用户头部的对象。 当用户运动时,内容将朝向视野边缘滑动而不会完全消失,从而很容易看到。 当用户凝视尾随对象时,该对象会更完整地进入视野。
我们将使用 SimpleTagalong.cs 文件来实现以下目的:
- 确定跟随对象是否在照相机边界范围内。
- 如果不在视锥范围内,请将跟随对象的一部分定位在视锥范围内。
- 否则,将跟随对象定位到默认的用户距离。
为此,必须先更改 Interactible.cs 脚本以调用 TagalongAction。
- 完成编程练习 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 中打开它。
需要添加以下各项:
- 将功能添加到 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);
}
}
- 试试看! 构建并部署应用。
- 观察内容如何跟随凝视点的中心移动,但不是连续跟随且不会阻挡它。