我一直都是 3D、VR 和 AR 技术的爱好者,而且我很幸运,到目前为止,我的工程职业生涯中很大一块儿做的都是这些领域的项目。
虽然 2010 年代 VR 行业的严冬让我对头戴设备的新品普遍持怀疑态度,但每次有新的头戴设备上市时,我还是能找回以前那种兴奋的感觉。
我在一家名为 Things, Inc. 的小型初创公司工作。这个 Inc 后缀看起来很严肃、很有企业范儿,但其实我们只有 3 个人,而且没人打领带或穿西装。不过我们有非常漂亮的连帽衫。
不用说,当苹果发布 Vision Pro 时,我们就怀着激动的心情想要尽快上手,因此我们决定第一时间预购。在等待这款头显发货的同时,我们开始使用模拟器做一些准备工作。
我们坐下来讨论了如何统治世界的计划。讨论的起点是“让我们做点有趣的事情”,最后收尾也是落在这上面(我们不太擅长统治世界)。我们如饥似渴地观看了 visionOS 的开发者视频,就好像在看一部大热剧集新出来的一季一样,然后就开始工作了。
当然,我们在投入《Rooms》这款应用的开发工作的同时,注意力不可避免地要分到这闪闪发光的新玩具上,不过我们觉得用几周时间来研究它也是挺划算的。
虽然没有什么东西能够替代实际拿到手的设备,但苹果准备了大量的开发文档,让我们能够非常清楚地了解这款头显的功能,这样我们立刻就能启动工作了。
我们构建的产品
言归正传(对之前的废话表示抱歉),以下是我们最终开发出来的内容:
主页面
我用了“最终开发出来”这个表述,是因为之前的决策过程非常曲折,后文详解。
这款应用会给用户展示一组事物的目录,这些事物是人们使用《Rooms》应用创建和上传的自制对象。当你单击某个类别或标签时,你会看到一组事物:
类别/标签页面
想要来只柯基?立刻安排!这里是显示对象及其信息介绍的细节视图:
细节视图
visionOS SDK 中有许多很酷的事情,其中之一是它允许你将 RealityView 直接嵌入到视图层次结构中,因此我们可以做出来一个真正的 3D 小组件,它的模型可以从窗口中拿出来:
从侧面看的细节视图
现在,你可以点击“添加到游乐场”,然后你的柯基犬会进入一个气泡里供你操作(否则这些对象该怎么用呢?),你可以把它放在你家中的任何地方,或者公园、办公室都行。
气泡中的柯基犬
下面是沙发上的柯基犬。
柯基犬在沙发上休息
你可以使用 3D 手势移动、旋转和缩放柯基犬,甚至可以肆无忌惮地放两只柯基犬,把它们放大到满房间那么大。
巨型柯基犬来袭
当然,能选择的不只是柯基,你也不用只呆在客厅里。下面是我们的团队在中央公园摆像素野餐的场景。
中央公园的像素野餐
幕后花絮……
介绍过我们所构建的内容后,接下来我可以告诉大家一些幕后花絮。
我们一开始的想法是构建事物,也就是编辑体素(voxel)。我们在 Rooms 应用中已经做了一个体素编辑器,如下所示:
Rooms 应用中的体素编辑器
所以我们很自然地想到“为什么不在 visionOS 上尝试这个想法呢?”毕竟,这么做又可能会出什么问题呢?
因此,我将所有 VOX 解析和网格构建代码从 C# 代码库移植到了 Swift 和 RealityKit 上,而 Nick 和 Jason 则负责应用的空间 UI。
正是在个当口,我们开始了解到这种新设备有着非常不同的交互模式,我们必须考虑到这一点。
悬停是用户的眼动操作
Apple Vision Pro 的独特特性之一是对用户隐私的保护。因此,与我以前使用过的头显不同,它不会自动暴露一些关键信息,例如用户的头部方向、注视方向、窗口位置,甚至用户在物理空间中的位置。
我们所能做的就是告诉系统可以与哪些元素交互,并且系统将负责检测用户是否做出了影响这些元素的任何手势。尤其要注意的是,悬停效果对应用程序来说也是完全不透明的:我们只能告诉系统我们想要悬停效果,但当用户将鼠标悬停在我们的组件上时,我们不会收到通知。
3D 图形也是这样:我们可以将某些实体标记为可悬停和可交互,但没有任何信息能告诉我们悬停操作是何时发生的。
因此,我们无法“智能地”对悬停状态或按需点击做出反应:任何可悬停或可点击的内容都需要作为一个 RealityKit 实体存在于场景中。
我们最初打算制作一个体素编辑器,也开始构建它了:
体素编辑器(没有成功)
但由于这一限制(当然,它存在的理由很充分),模型中的每个体素都必须在每个面上都有一个单独的点击目标,这样就算是比较小的体素做起来成本也是非常高的。
可这时候我们还没有用上头显!也许有一个惊喜在等着我们。我们也不能乐观地假设这款头显的性能非常之高,足够处理数千个实体而不出问题。
像我这样的工程师在面临“痛苦地重写一个主要软件”的前景时很容易做出一厢情愿的想法。我的意思是我总是会过分乐观。
拿到头显
随着头显发货日期的临近,我们决定在纽约见面,这样我们就可以花一周的时间一起开发这款应用了。
为了确保我们一定能及时收到头显,我们每人都买了一个,并将它们全部发到 Jason(我们的首席执行官)的家里。当 UPS 卡车运来货物时,他监视着整个运送过程,站好了这班岗。
我们第一次试用头显。
犹如魔法一般。
我们完成了新手教程。实在太棒了。清晰的高分辨率显示、完美的眼动追踪、自然的手势、身临其境的空间音效、令人愉悦的用户界面。
我们使用“杯垫测试”来测试头显延迟,也就是在佩戴头显时来回扔杯垫,看看它的延迟是否足够低,低到我们戴着头显也能抓住杯垫的水平。
准备“过山车测试”
我们意识到,即使没戴头显,我们也没法抓住杯垫,因为它们的形状很奇怪,所以这不是什么好测试。如果你是为了科学严谨性而阅读这篇文章,很抱歉让你失望了。
问题
尽管这款头显是市面上最先进的,并且一开始的体验非常出色,但我们很快就意识到我们的愿望和现实之间存在一些差别(在这种情况下,现实往往会获胜):
基于凝视的交互很直观,但不够精确(达不到体素编辑所需的水平)。
用眼睛来做精密工作并不是很舒服。我们的眼睛很快就会因为重复地从一个表面移动到另一个表面来放置体素而感到疲劳。
然而,我们也注意到了一些意想不到的好事情:
头显的图像锐利清晰,没有任何模糊的情况,而且分辨率非常高,即使我们戴着头显也可以使用手机。
滚动操作太太太有意思了。为什么滚动如此有趣?它不应该这么有意思啊,它只是滚动操作而已。甚至设置用户界面也很有趣,因为有很多设置,你可以滚动浏览它们。
其他手势也很有趣(拖动、旋转、缩放)。
很多指点操作
从硬件的角度来看,在场景中放置数千个等待凝视激活的实体是不可能做到的。从人体工程学的角度来看,用我们的眼睛来选择体素是行不通的。
好的,如果基于凝视操作的体素编辑没法用了,我们需要弄清楚用户该如何选择他们想要放置体素的位置。
我们四处寻找答案,最后把目光投向了自己的手臂。如果我们可以简单地用食指指向我们想要修改的体素,并做一个手势来编辑它会怎么样?
因此,我使用 ARKit API 实现了手部跟踪,这需要我学习一些手部解剖学知识来理解开发文档,例如,当某些东西返回“从掌指关节到近端指间指关节”的向量就需要这种知识来搞清楚是什么意思。
于是用户的手指变成了一个“激光笔”,他们会并拢手指或用拇指“点击”来放置体素。
手指操作解决方案
我和其他人一样喜欢用远端指骨来发射激光,但我们很快意识到这不够精确,而且实际操作起来也很累。
我们遇到了人类肌肉和关节的硬件限制。
我们来看看其他应用
我们在 App Store 上查看了其他许多 visionOS 应用。我们担心商店里会遍地都是酷炫的应用,以至于我们永远没有机会在令人眼花缭乱的应用海洋中受到关注。但令我们惊讶的是,我们错了:visionOS 的应用非常少,至少从我们的标准来看,好的东西就更少了。
我的意思是,商店里有很多商业和生产力应用,但我必须承认,我对空间计算的未来科幻时代的梦想和愿景并不包括“查看悬停在咖啡桌上的电子表格”。我对未来时代的梦想根本不涉及咖啡桌。
我们看到一些应用程序本质上是带有一些 3D 元素的 2D 应用,包括许多流行的手机游戏,但在虚拟 2D 表面上玩它们的体验并不比在真正的平板电脑上玩它们更好。
Things, Inc 空间计算愿景的大危机
夜幕降临。我的意思是,当时是冬天的下午 6 点,但这也是一种比喻:如果应用商店中没有令人难以置信的、引人注目的应用程序,并且我们的想法也无法实现,这是否表明我们不可能做出来一些有趣的事情?这一切只是浪费时间和金钱吗?
我们决定放弃。
我们有很多想要在 Rooms 中实现的功能,但不这样做的机会成本开始困扰着我们,因此我们决定将头显放回(非常昂贵)的盒子中,并把工作重心转回我们已经开发出来的,有着一定用户群并且需要我们关注的应用上。这是一个成熟的决定,也是一个值得我们回顾并感到自豪的坚定决策。
既然我们决定完全投入其中,我们甚至开始列出我们要在 Rooms 中做的所有事情:
就这样,Things, Inc. 的空间计算愿景的大危机开始了。无论危机持续几个月,我们都必须勇敢地面对这样充满挑战的时期,希望我们最终能在遥远的未来回到 visionOS。
结果这段时期持续了十五分钟。
Things, Inc 空间计算的第二个开拓时代
当我们埋葬这个应用并准备继续前进时,我们的社区经理 Matt Fogarty 做了最后一次尝试,并真正做了一样我们以前从未做过的事情:像用户一样认真使用这款应用。彼时,我们所做的最多的事情就是放置一两个对象并立即尝试编辑它们,结果就是那种我们之前描述的破碎体验。相反,Matt 根本没有打开体素编辑器,只是从库中选了几个对象并组装了一个小场景。
我的同事 Nick 也试了下,然后是我,然后是 Jason。我们的想法是“是的,我们要放弃这个应用,但让我们最后看一眼”。但后来我们意识到,如果我们根本不使用体素编辑器……它还是能用的。但我们已经做出了决定!
“其实这很好玩啊。” — Nick
几分钟后,我们脑海中形成了一个新计划:使其达到足够好的状态,然后制作一段视频发布在推特上,但除此之外就不做别的了。
只是一个视频。因为制作一个实际的应用是不可能的,需要几个月的时间。我们非常擅长制定这些坚定、经过深思熟虑的计划和现实的时间表。
“我们在本周末之前发布应用怎么样?” — Jason
于是就这么定了。
到那时,我们已经充分了解了这款头显的功能和缺点,我们终于可以想象如何使这个应用发挥作用。我们把它从垃圾桶里翻出来,并决定把应用设计成浏览我们丰富的物品目录,然后将 3D 模型放置在你的房间中,让你可以组装小场景来获得乐趣。
用户界面系统
我深入研究了 3D 数学、实体和变换,在解决诸如“为什么熊猫出生时屁股朝向用户而不是正面?”等深刻的线性代数问题时,偶尔会被 Swift 的难题困住。
Nick 和 Jason 设计并构建了一个漂亮的系统,用于浏览 Things 目录、从 Firebase 加载数据并将其整齐地呈现到主页、类别甚至搜索中。
类别 UI
我们做了大量工作来以最佳方式组织管理库中的数千件物品,这样人们就能有充足的资源来构建他们的有趣场景了。
构建 Things
我们遇到的一个问题是,当你向场景添加一个新对象时,用户有时很难注意到这个对象的现身,因为他们的注意力可能集中在 UI 上。
更糟糕的是,没有可靠的方法(据我们所知)相对于 3D 空间中窗口的位置来定位 3D 对象,因此很难将新对象定位在用户不会错过的可预测位置上。
我们的解决方案?
气泡里的熊猫
只需将新物体放入气泡中即可!它将其标记为一个新对象,因此用户就能知道它刚刚添加进来了,并且很容易注意到它的存在。Nick 甚至添加了空间音频,方便用户定位气泡的位置。
2024 年的空间计算应用程序中的气泡会发出什么声音?我不知道。我们做的音频充满未来感,但也很友好。“有机机器”是我们用来描述它的术语。
怎么删除东西?
另一个有趣的问题是:移动、旋转和缩放很容易,但如何删除不想要的东西呢?
我们可以有一个垃圾桶,但这会给场景带来干扰,我们不知道把它放在哪里(记住,我们不会自动知道用户在场景中的位置),然后用户会想要移动它,诸如此类。
所以我们决定采用一种有趣的方法:将一个东西拖到地板下,然后它们会变成红色并爆炸成一团灰尘。等我们学会了如何制作粒子效果后,就把这种效果添加到了更多的地方。谁不喜欢粒子发射器呢?
就是这样。功能开发完成。到周四早上,我们宣布该应用程序的功能已开发完成,并坚定地宣布“从现在开始不再有任何新功能,只有错误修复。”
正如你可能会猜到的那样,这样的决定也不能坚持下去。
保存或不保存
一开始,我们的计划只是纯粹为了好玩而查看 3D 模型,并且你无法保存你创建的场景。
这样我们就完成了。我们开始使用这款应用,创建一些场景。但当我们开始享受乐趣时就看到了风险。我们开始感到失望,因为我们会失去自己创造的东西。
我远远就能闻到特性缺失的味道,空气中弥漫着一种相当强烈的特性缺失的气味。
我们知道这是一个风险:如果我们从创造某些东西中获得乐趣,我们显然会想要保存它。
只有两个选择:
(a)减少乐趣,这样人们就不需要保存功能了
(b)实现保存功能
“当你给老鼠一块饼干时……”——Nick
我不熟悉这句俗语,也不是动物学专家,但我相信给老鼠一块饼干之后的问题是“它接着想要一杯牛奶”(尽管我很难想象老鼠会如何喝它)。
所以我们开始讨论……如果我们有办法挽救呢?我们只做一个小特性就行了。
“听到了吗?这就是特性悄然潜入的声音。”——Bruno
值得庆幸的是,由于 SwiftUI 的机制,我们的数据已经采用了大部分可序列化的格式,不会造成太大的困难。Nick 在创纪录的时间内构建了整个保存/加载用户界面……并在我们认为基本上不会遇到问题的地方发现了很多隐患:用户如何重命名、覆盖、删除、收到有关未保存更改的警告,等等?庆幸的是这些隐患都解决了。
中央公园之旅
那一天,外面阳光明媚,由于我们那时候还没怎么离开过公寓,所以决定步行几个街区到纽约中央公园。但我们当然不能像普通人一样在中央公园散步,我们必须带着头显去那里尝试一下。
结果很成功:应用程序运行良好,并且将一只体素狗放在一只真正的狗旁边是很有意思的操作,(出于狗的隐私考虑,我不会在这里放上当时的照片,而且那只真狗正在上厕所。)
下面是 Nick 在一株虚拟的柠檬树下抚摸一只虚拟柯基犬的照片。
哪个体素模型做得更好?
我们做测试时,确实有人过来搭茬。
“新玩具?” ——中央公园的路人问我们
他们问题的语气好像在说我们玩物丧志,于是我们明确表示我们根本没有玩得很开心,这纯粹是为了工作,对此路人似乎很满意,仿佛在说“这样就可以了,只要你们不开心就好。”
但其实我们特别开心。
提交应用前的最后准备
拍摄宣传视频和为应用商店制作截图并不容易,因为它需要一个特殊的过程,就是从头显中获取高分辨率图像。Jason 花了几个小时来研究这个操作。事实证明,这会导致头显明显发热,所幸这个问题很容易解决:
冷柜里的非常酷的头显
当我写最后一段时已经是周五午夜了,我们刚刚将应用提交到了 App Store 审核,所以我们已经在预定的时间内成功完成了这个应用程序。
它没有我们想要的所有功能,但它有我们认为至关重要的所有功能:它是一块饼干加半杯牛奶。
经过这几天的紧张工作,我感到无比疲惫,但矛盾的是我又非常有活力。我很期待看到用户会使用这个应用做些什么事情!
(该应用已上线:https://apps.apple.com/us/app/a-bunch-of-things/id6477489901?uo=2)
评论