2018 年 8 月

33 卷,第 8

此文章由机器翻译

HoloLens-混合现实和 Fluent 设计

通过Tim Kulp |2018 年 8 月

Microsoft 投入了硬混合的现实 (MR) 开发在由于它在 2014 年引入 HoloLens 和在五月的 Build 2018 大会上,它提供丰富的深入 Unity 开发环境中的新增功能的 MR、 以及 UI 设计最佳实践。在本文中,我将利用在生成演示如何使用 Microsoft Fluent 设计系统构建沉浸式体验 MR 中的介绍的技术指导 — 具体而言,一个 HoloLens 应用,使非语言孩子们通过 pictograms 进行通信。

Microsoft 的 Fluent 设计系统使用三个核心原则提供卓越的体验。它们是:

自适应:MR 必须桥接和 mingle 现实世界和数字的组件来创建具有全面的体验。在这种情况下,环境,必须留意 UI 时增强 (但不是会替代) 用户的实际体验。

感同身受:在 MR 感同身受设计着重于了解用户的意图和需求中的应用体验。作为示例,并不是所有用户可以都使用太多的事情的手势,因此 HoloLens clicker 和语音命令提供输入的形式所感同身受到该用户的需求。

美观:美观的应用是一项重大挑战 MR 中。设计人员或开发人员,必须扩展的实际体验,但不使它。需要进行仔细的规划和合适的工具。

Unity 是最常见的工具,用于构建 MR 体验。Unity 中,根据 90%的 HoloLens 和 MR 应用是利用其开发环境。尽管 Unity 具有其自己的 UI 系统,它并不轻松地转换到 Fluent 设计。Microsoft 团队已生成混合现实工具包 (bit.ly/2yKyW2r) 和混合现实设计实验室 (bit.ly/2MskePH) 工具,帮助开发人员构建出色的 Ux,通过组件的配置。使用这些项目,开发人员可以避免复杂的图形设计的工作并专注于自己的应用程序的功能。混合现实工具包和设计实验室还记录了许多代码示例。在本文中我使用混合现实工具包 2017.4.0.0 Unity 包生成接口并向您演示如何将各种组件一起放入您自己紧密结合的唯一的界面。

设置你的 Unity 环境之前,请确保完成混合现实工具包中的入门教程 (bit.ly/2KcVvlN)。对于此项目,我使用 (在撰写本文时) 最新的 Unity 生成 2018.2.08b。使用 Unity 2018.2 所需的更新混合现实工具包,但升级不会导致在本文中实现的功能的任何冲突。

为 MR 设计用户界面

出色的 MR 体验开头的有效 UI 流。不同于 Web 或移动应用,MR 应用的 UI 具有一个大未知: 环境。Web 开发中,您必须是一种注意屏幕分辨率和浏览器功能中的移动开发时,其像素密度和电话功能。但在 MR 中的用户的物理环境和环境变量的性质变得极为重要。

通过面向特定的环境,我可以优化的物理空间以及正在使用的设备的特定功能。在我的示例应用中,我设计为教室设置其中的学生将应用用于其教师。这是亮堂和相对较安静的环境,它是从仓库或晚上俱乐部内部设计非常不同。计划你的环境的 UI。

环境是不仅用户的外部,而且还取决于用户的设备功能。当考虑我的 UI,我需要注意可能要使用的控件。考虑用户的环境和功能,语音命令将无法播放由于重要的作用缺乏口头通信。手势可限制,因为我的目标用户也可以正常汽车技能挑战。这会导致大按钮和具有 HoloLens clicker 之类的工具的用户来选择相应的按钮。

这一点后,我需要选择如何布局我的 UI 进行美观的设计。如果你是 Web 开发人员使用 Bootstrap (或类似的 UI 框架),您熟悉在网格中生成。在 UWP 中,您可以如 StackPanel、 网格和画布的布局控件。在混合现实工具包有对象集合组件。

可以在资产下的混合现实工具包中找到对象集合组件 |用户体验 |脚本 |对象集合。若要使用它,请在您的场景中创建空游戏对象。命名空游戏对象"MainContainer"并将对象集合组件添加到空游戏对象。出于测试目的,将多维数据集作为子对象添加到 MainContainer。设置多维数据集的范围,请为 0.5 x、 0.2y,0.1z 使它看起来像一个精简的矩形。现在重复的多维数据集作为子对象向 MainContainer 具有九个多维数据集总共八倍。

多维数据集添加后,在检查器要应用于子对象的对象集合布局中按更新集合按钮。默认情况下,使用图面类型的普通对象集合。对于我的 UI,我想要环绕的用户感觉更多沉浸式的集合。若要执行此操作,更新到球体检查器中的对象集合的图面类型。现在所有多维数据集应出现如中所示图 1。对象集合提供了多个面类型以允许 UI 特定情况下吸引用户。本文稍后我将向您展示如何使用不同的图面类型以达到不同的目标。

更新到球体的图面上的类型
图 1 更新到球体的图面上的类型

我们要生成什么?

非语言的传达子项具有 pictograms,它们使用与教师来表示其需求的书籍。每个象形图是词或短语的子和教师一起生成。在本文中,我将介绍如何生成要考虑的通讯簿 HoloLens,以便学生可以生成的句子其教师与进行通信的 MR 体验。

我将首先使用对象集合添加一系列按钮供用户选择此选项可以生成一个句子。这些按钮将 pictograms。首先,通过添加资源 |数据文件夹复制到您项目的窗口。在 data 文件夹内创建 words.json 文件以表示在应用中的单词。示例代码采用一个短单词文件来为简单起见。

在项目窗口中,创建脚本文件夹并在该文件夹创建一个新 C# 脚本调用 WordLoader。此组件读取 words.json 文件,并将其转换为 C# Word 对象的集合。在设计实验室中没有演示从文件读取数据并显示 MR 体验中的已完成的示例的示例项目。我将调整要使此示例简明和熟悉的如中所示的定期表项目代码图 2。签出在段表项目,请bit.ly/2KmSizg实现其他功能和基于读取的数据文件并将结果绑定到对象集合的功能。

图 2 WordLoader 脚本

[System.Serializable]
class Word
{
  public string category;
  public string text;
  public string image;
}
[System.Serializable]
class WordsData
{
  public Word[] words;
  public static WordsData FromJSON(string data)
  {
    return JsonUtility.FromJson<WordsData>(data);
  }
}

接下来,编写代码所示图 3 WordLoader 组件。此组件将从 JSON 文件加载单词,并将它们为按钮添加到对象集合。组件中有两个公共变量:父级是保留字的对象集合和 WordPrefab 是预设可用于表示 MR 体验中的单词。

图 3 从 JSON 文件加载单词

public class WordLoader : MonoBehaviour
{
  public ObjectCollection Parent;
  public GameObject WordPrefab;
  private void OnEnable() {
    if(Parent.transform.childCount > 0)
      return;
    TextAsset dataAsset = Resources.Load<TextAsset>("Data/words");
    WordsData wordData = WordsData.FromJSON(dataAsset.text);
    foreach (Word w in wordData.words) {
      GameObject newWord = Instantiate<GameObject>(WordPrefab, Parent.transform);
      newWord.GetComponent<CompoundButtonText>().Text = w.text;
      newWord.GetComponent<CompoundButtonIcon>().OverrideIcon = true;
      string iconPath = string.Format("Icons/{0}", w.image);
      newWord.GetComponent<CompoundButtonIcon>().iconOverride =
        (Texture2D)Resources.Load<Texture2D>(iconPath);
    }
    Parent.UpdateCollection();
  }
}

到父级已加载的所有单词后,调用 Parent.UpdateCollection 将排列基于对象集合组件的布局的新创建的按钮。更改属性在对象集合组件中,每次调用更新集合,以确保正确更新所有游戏对象。

现在在 Unity 编辑器中创建一个空游戏对象名为 Managers,其中包含所有场景的实用程序组件。将 WordLoader 组件添加到管理器,然后将父级设置为 MainContainer。最后,设置 WordPrefab 使用 Holographic 按钮预设 (位于 HoloToolkit |用户体验 |预设 |按钮)。这些按钮实现 Fluent 设计概念,如使用 light 以显示焦点和操作。当用户发现高亮显示的按钮时,他知道选择的内容。

现在运行该应用程序创建 word 数据文件中的每个单词的按钮 (请参阅图 4)。Holographic 按钮将容纳球体中的用户。在播放模式下中, 任意对象集合的图面类型尝试使用其他布局更新。调整单元格间距和行计数以找到合适的组合为你的体验。记住每个更改,以查看在编辑器中的更改后更新集合。

查看为 Holographic 按钮对象集合中的单词
图 4 为对象集合中的 Holographic 按钮查看单词

与用户保持

生成对象集合后将在世界中将它设置为特定的坐标。当用户移动时,仍会保持最初是对象集合。为教室这样行不通因为子级不始终保持在其办公桌。我需要更新 UI,以继续使用该用户,随着在真实世界各地。在 Fluent 设计需要适应环境,即使这个人移动并更改环境。

在 Build 2018 大会上,技术会话 ("构建应用程序对 HoloLens,仓库大规模bit.ly/2yNmwXt) 所示构建空间大于表顶部的应用程序面临的挑战。保持 UI 组件时阻止的对象,如铲车仓库到用户的可访问性来保持 UI 中显示这些范围上移动的内部设计等项目的空间。混合现实工具包提供了一些工具来使用解算器系统解决的一些问题。

解算器系统允许调整其大小或位置基于通过世界上的用户的移动游戏对象。在 Unity 中,可以看到一些求解器场景使用编辑器中的工作原理。若要添加解算器,请选择 MainContainer 对象并添加 SolverBodyLock 组件 (位于 HoloToolkit |实用程序 |脚本 |求解器)。SolverBodyLock 组件允许按钮让用户的球体,因为用户在将移动整个空间 MainContainer 也随之迁移。若要测试这一点,在编辑器中运行你的应用,并使用箭头或 WASD 键的世界空间中移动。您会注意到前进、 后退和端到端移动保留与你 MainContainer。如果旋转照相机,MainContainer 不遵循你。

若要使他旋转空间中的用户操作的 UI,请使用 SolverRadialView,它默认情况下保存用户的外围视图内的对象。可见的对象是可以增加或减少基于组件的设置。在此用例,我不希望跟踪用户,他发现,因此 SolverBodyLock 就足够的用户界面。它使按钮与用户,但并不总是在其人脸列表。

保留大小

在我的应用程序中,我希望促使客户迁移通过教室设置。在先生,就像现实生活中,如果人们移开一个对象,该对象将显示较小。这就会产生问题:使用的视线移动到远处对象上的目标 UI 组件可能很困难,和图标可能很难识别从远。ConstantViewSize 解算器解决此问题通过扩展 UI 组件,或向下基于用户的距离。

对于此示例应用,你要添加一个组件,用于生成的句子的用户。每个 MainContainer 中的按下按钮将添加到句子。例如,如果用户想要说,"我需要能够",他需要单击"I"按钮,然后"是"按钮,然后"到"按钮。每次单击将单词添加到句子容器。

在层次结构中创建一个新的空游戏对象并调用它的句子。将对象集合组件添加到句子、 平面和行的图面类型设置为 1。这将创建一个平面接口,不会破坏到内容的行。现在,添加多维数据集到句子的游戏对象,以便您可以查看在操作中的常量大小解算器。稍后我将添加单词的按钮中。将多维数据集的规模设置为 x = 1.4,y = 0.15 z = 0.1。如果您现在启动该应用程序,并移动空间,白色多维数据集将收缩和增长移动时更远随手可得,更接近于它。

若要锁定 cuboid 的可视大小,请将 SolverConstantViewSize 组件添加到句子对象中。此外可以使用的最小和最大刻度范围设置,以便您可以控制想要扩大或收缩的 UI 组件的大小限制该组件的小数位数和在何种远距离,这样就可以缩放到教室上、 表中的组件向仓库。

有多个求解器包括 Momentumizer 和图面磁性混合现实工具包中提供。我鼓励您查看解算器系统和发展自己 MR 的体验与一个用户界面,可以使用真实世界空间中的用户 (bit.ly/2txcl4c)。

句子和接收方

若要启用 MainContainer 要连接句子对象使用的按钮,我实现接收方,MainContainer 中的按下的按钮中接收事件并将该按钮的内容添加到该句子。使用种交互的对象和混合现实 Toolkit 内置的接收方模式,连接 prefab 按钮位于 HoloToolkit |用户体验 |按钮文件夹很简单。

创建一个新 C# 脚本调用你的项目,在脚本文件夹中的接收方,如中所示图 5。更改脚本,以便从 MonoBehavior 继承到 InteractionReceiver。创建一个公共变量以保存对句子游戏对象的引用,然后实现 InputDown 以响应用户的重写方法单击 Holographic 按钮上的操作。

图 5 收件人 C# 脚本

public class Receiver : InteractionReceiver
{
  public ObjectCollection Sentence;
  protected override void InputDown(GameObject obj, InputEventData eventData)
  {
    switch (obj.name)
    {
      default:
        GameObject newObj = Instantiate(obj, Sentence.gameObject.transform);
        newObj.name = "Say" + obj.name;
        Sentence.UpdateCollection();
        break;
    }
  }

在 InputDown 方法中,创建一个 switch 语句,用于检查 obj 游戏对象的 name 属性。现在,创建的默认条件,无论游戏对象名称出现这种情况。在默认的语句,我需要调用对象并创建它的句子游戏对象下的新实例。这将注册与接收方的情况下在句子对象集合中创建按钮的新实例。如果句子对象中按下按钮,没有任何反应。测试之前,删除白色 cuboid 占位符,以便您可以看到显示在对象集合平面上的按钮。

若要连接到接收方 MainContainer 中的按钮,需要几行代码添加到 WordLoader。应用程序加载的单词,每个将被注册为 Interactable 为接收方。Interactables 是使用接收方对事件发生时做出反应的 InteractableObject 组件的游戏对象的列表。在 WordLoader onEnable 方法中,添加以下代码正下方的 childCount 检查:

var receiver = GetComponent<Receiver>();
if (receiver == null)
  return;

此代码检查以确保接收方存在。然后在 foreach 循环中的单词,添加以下代码加载为按钮的图标后:

receiver.Registerinteractable(newWord);

Registerinteractable 接收方将游戏对象添加到 interactables 的列表。现在单击中 MainContainer 全息版的按钮触发接收方执行 InputDown 方法,并创建一份被单击的按钮。

与一些次要重新配置的 MainContainer 对象集合的单元格大小和位置,将会看到图中所示类似图 6

MainContainer 和更新后的句子对象集合
图 6 MainContainer 和更新后的句子对象集合

虽然我用 Holographic 按钮在此示例中,种交互组件可以应用到的任何内容为文本自定义网格中。让你的创造力有助于 imagine 令人惊叹的接口。请记住,MR 的目标之一是合并数字和物理体系,以便使它们协同工作。

利用文本到语音转换

Fluent 设计的一部分,正在感同身受到用户的需求。在此示例中,要启用这些缺少口头语音,以表达自己的思想。现在,您需要使用文本到语音转换可以说出用户对她句子中生成的内容。HoloToolkit 提供了出色的组件使用最少的代码或配置执行此操作。如果您不使用 HoloLens,请查看我的 MSDN 杂志 》 文章"使用认知服务和混合现实"(msdn.com/magazine/mt814418),以查看如何使用通过 Azure 认知服务文本到语音转换。

若要开始使用文本到语音转换,将添加到你的项目层次结构的音频源。文本到语音转换组件使用此生成的用户听到的音频。现在,添加文本到语音转换组件 (位于 HoloToolkit |实用程序 |TextToSpeech) 到经理游戏对象。我使用经理游戏对象作为的所有实用程序方法 (接收方,则文本到语音) 来集中管理事件和与这些事件会发生什么情况。在这种情况下接收方将使用文本到语音转换组件说使用同一接收方你的设置用于将单词添加到该句子的句子。将文本到语音转换组件设置为使用刚创建的检查器中选择该音频源。

在接收方,我来检测这句话中存在的任何单词,而因此,我将添加一个按钮,会显示在句子。添加到接收方组件调用 SayButton 一个新游戏对象公共变量。

public GameObject SayButton;

这将是预设可用作 Say 按钮。在 switch 语句的默认块中添加以下 if 语句之前将新对象添加到该句子:

if (Sentence.transform.childCount == 0)
{
  GameObject newSayButton = Instantiate(SayButton, Sentence.transform);
  newSayButton.name = "Say";
  newSayButton.GetComponent<CompoundButtonText>().Text = "Say: ";
  GetComponent<Receiver>().Registerinteractable(newSayButton);
}

在这种情况下时句子对象中没有任何子级,添加在任何其他按钮之前的假设按钮。这将避免 Say 最左边的任何句子的句子对象。接下来,在切换到通过名称来检测 Say 按钮中创建新的 case 语句。请记住,此开关取决于 obj.name 并创建此按钮时将名称设置为"Say。" 代码如下:

case "Say":
  StringBuilder sentenceText = new StringBuilder();
  foreach (CompoundButtonText text in
    Sentence.GetComponentsInChildren<CompoundButtonText>())
  {
    sentenceText.Append(text.Text + " ");
  }
  TextToSpeech tts = GetComponent<TextToSpeech>();
  tts.StartSpeaking(sentenceText.ToString());
  break;

这种情况下通过名称来检测 Say 按钮,然后遍历所有子级的句子来生成 TextToSpeech 组件的单词的字符串为一个句子说。用户完成时生成语句,他可以按假设按钮来表达他语句。为简单起见我没有实现的 HoloToolkit 文本到语音转换管理器 (bit.ly/2lxJpoq),但最好避免像用户反复地按 Say,从而导致文本到语音转换的情况尝试在同一时间说出多个事物的组件。

总结

Fluent 设计使用 MR 是自然的选择。混合现实工具包和混合现实设计实验室之类的工具是很好 springboards 来构建自适应、 感同身受且美观的体验。在本文中我介绍了如何实现的一些显示生成 2018 MR 体验。通过使用对象集合作为布局工具,解算器系统以保持 UI 与用户浏览空间,然后连接来体验与集中的事件管理的接收者,我介绍了如何快速生成 MR 应用。

使用混合现实工具包中的示例,可能需要进一步新界面选项和功能具有此示例应用程序。查看从 Build 2018 以获取有关如何构建混合物理和数字世界的卓越体验的更多灵感 MR 会话。


Tim Kulp是考虑到通过机 Baltimore,md 的新兴技术主管他是混合的现实、 人工智能和云应用开发人员,以及作者、 画家、 爸爸和"wannabe 疯狂科学家创建者"。 在 Twitter 找到他: @tim_kulp或通过 LinkedIn: linkedin.com/in/timkulp

衷心感谢以下技术专家对本文的审阅:将咦 (Balti 虚拟)


在 MSDN 杂志论坛讨论这篇文章