写点什么

Vision Pro 开发实践(一)

  • 2024-04-02
    北京
  • 本文字数:4812 字

    阅读完需:约 16 分钟

Vision Pro 开发实践(一)

简介

Vision Pro 是苹果公司的首款头戴式“空间计算”显示设备,于 2023 年 6 月 6 日在“WWDC2023”正式发布,同时推出的还有专为 Vision Pro 打造的操作系统平台 visionOS,以及一整套“新的”开发工具,之所以打引号,是因为用于 Vision Pro 开发的工具和编程语言并没有多少改变,而更多的是需要开发者的开发思维变化。


最近公司组织了几批人员,前往苹果实验室实地体验 Vision Pro,并在现场进行适配调试。我有幸参与其中,现在就把整个过程的体验分享给大家,同时分享一些 visionOS 开发的基础。


别具一格的交互

要了解 Vision Pro 上应用的适配与开发,就要先了解它的人机交互方式。现在市面上大多数的 VR 设备采用的都是通过手柄进行指向、选择和点击的操作,辅以识别简单的手势(比如左右滑动等)和头部活动(点头、摇头等)。这样的交互方式最大的优点就是可以降低成本,手柄的制造工艺已经相当成熟,内置陀螺仪和红外感应、NFC 元件都不是什么难事,同时减少 VR 设备的传感器数目从而降低重量,延长续航。


但是苹果显然认为这种交互方式不够理想,如果体验过其他苹果产品就会发现,苹果的设计师似乎一直倾向于利用用户自己的身体来实现目标需求,指纹识别,面部识别,多指手势以及“嘿,Siri”都是一贯如此。而在 Vision Pro 上,苹果认为用户的眼睛和手完全就可以胜任手柄的工作,所以他们提出的交互方式是别具一格的“眼球追踪+手势识别”。


苹果通过遍布 Vision Pro 眼部周围的传感器,实现了精读极高的眼球追踪技术:



这样一来,用户的眼睛就变成了鼠标的指针,想要选中哪个元素,只要看向它就可以了。就我实际的体验而言,精度和准确率都非常之高,就连非常小的 UI 元素都可以准确的选中:



不止如此,苹果还通过 Vision Pro 下面的一圈传感器进行手势的收集和识别:



苹果下了这么大的血本只为了一个目的:无论用户的手放在哪里,都可以实现高精度的手势识别,面前,腿上,沙发上都可以。在首次开机的学习引导里,苹果给出的提示语就能非常好的概括:“you can place your hands wherever you feel comfortable”


除了不限位置,Vision Pro 还可以准确的识别单击、捏住和双手手势:



Tap: 同时点击拇指和食指,表示点击显示屏上的虚拟元素,相当于点击 iPhone 的屏幕。


Double Tap: 双击手势。


Pinch and Hold: 类似于点击并按住手势,执行突出显示文本等操作。


Pinch and Drag: 可用于滚动和移动窗口。您可以水平或垂直滚动,如果用户加快手势速度,交互界面也会相应地调整速度。


Zoom: 双手手势之一,可以把手指捏在一起,通过拉开手势进行放大,窗口大小也可以通过在角落拖动来调整。


Rotate: 另一个双手手势之一,它将涉及将手指捏在一起并旋转双手以操纵虚拟对象。


虽然乍一看起来通过眼球追踪和手势识别来进行日常的操作比较繁琐,你要先看着想要点击的地方,再捏一下手指,但实际体验下来整个过程非常流畅、自然,没有违和感,与苹果生态一贯的操作习惯一脉相承,基本不需要额外的学习成本。但是这种便利的代价也很明显:大量的传感器增加了设备的成本(3w+)和重量(600-650g),同时即便是连接外接电池,最长也只能实现 2 小时的续航时间。


现在还无法断言苹果这套交互方案和手柄对比谁好谁坏,但是正如以往苹果率先提出的“触屏取代实体键盘”,“触摸板手势”以及“全面屏交互”等方案,经过长时间的市场检验,最终还是别广大厂商采用并效仿,这一次苹果在 Vision Pro 上提出的这套全新的“空间交互方案”日后很有可能成为 VR 设备采用的主流方案。

移植的适配逻辑

不少研发同学都会有疑问:我的 APP 没有单独对 Vision Pro 做过适配,那么它能直接在 Vision Pro 上运行吗?可以的话它原始的适配逻辑又是什么?


首先对于第一个疑问,答案是肯定的,就算没有经过任何适配,app 依然可以在 Vision Pro 上正常运行,所有的交互都能执行,甚至可以通过盯住屏幕左侧用捏住并拖拽实现“左划返回”手势。


至于原始适配逻辑,如果有曾经在 iPad,或者 M 系列芯片 Mac 电脑上运行手机 App 的经验,就能大致明白他们在 Vision Pro 上的适配逻辑了,就是在屏幕上创建一个手机屏幕大小的“模拟器”,让 app 在上面运行。这里以我们“京东到家”的 app 为例



当然,如果 app 做过 iPad 的适配,那么在 Vision Pro 上的展示样式则会优先展示为 iPad 的样式,比如京东主站 app:



同时,在 App 下端会展示两个控制元素,一个小圆点和一个横条。眼睛看向小圆点的话,它会变成一个叉号,用于关闭 App(退至后台),需要完全杀死 App 的话,逻辑则类似于 Mac 电脑的杀死进程,需要同时按住 Vision Pro 的返回键和表冠 2 秒,然后再应用列表中找到 App 强制结束



那既然不需要适配也可以正常运行,我们是不是就不需要单独进行 VisionOS 的开发了呢?当然不是。未经适配的 App 虽然能够正常运行,但是它的展示样式毕竟是为了手机端而设计的,在 Vision Pro 上,屏幕从 2D 的平面拓展到了 3D 的空间,而在“空间”中,Vision Pro 更着重于凸显“无界”的概念:



苹果更倾向于让 App 没有边界,不局限于手机屏幕的条条框框中,更加融入到空间之中,同时 visionOS 也允许 UI 元素超出 App 的界面边界。所以对于 Vision Pro 的适配,更多的是从平面到空间的思维转变,如何让 App 在“空间”这一画布上更好地呈现设计者想要表达的意图才是重中之重。要进行“空间计算”开发,就要了解基础的 visionOS 开发机制,下面我将介绍一些入门的知识。

开发从入门到略懂

首先,在 Xcode15 中创建 app 时,除了以前的 iOS、macOS 等平台,现在可以选择 visionOS 平台进行开发,此时 SwiftUI 提供了许多专为 Vision Pro 准备的新 API,以供空间应用开发。



选择 visionOS 平台后,可以设置场景类型和氛围样式:


场景类型

visionOS 的 app 中可以创建三种场景类型:


Window 形式



主要用于展示 2D 内容,iPhone 和 iPad 的 App 在 Vision Pro 中展示默认就是采用这种形式,如果 app 需要展示文本内容、视频或者弹窗等等,可以创建这种场景来进行展示。Window 形式也可以展示 3D 元素,但是无法在空间中 360 度的查看 3D 模型,因为 Window 在空间中是以类似于镜子的形态呈现,绕到后面时只能看到白色半透明的面板。



Volumes 形式



苹果官方描述说这是最适合展示 3D 模型的场景,当在 app 中创建了 Volumes 类型的场景时,visionOS 会开辟出一个 3D 的空间用于放置 3D 元素,如果我们想要放置商品的 3D 模型进行全景展示,可以创建这种场景


Spaces 形式



在这种场景下,visionOS 会将使用者周围全部设置为可以放置 UI 元素的区域,周围的所有空间都可以作为开发者的“画布”,你可以在任意位置放置 2D、3D 模型。但是需要注意的是这种场景理论上只应创建一个。

氛围样式

氛围样式是 app 的呈现形式,分为.mixed, .progressive,.full 三种,我们可以通过一个图来清晰明了的理解它们分别代表的意思:



在工程当中也可以通过代码来进行设置,以实现在不同氛围之间切换:


@mainstruct MyImmersiveApp: App {    @State private var currentStyle: ImmersionStyle = .full

var body: some Scene { WindowGroup() { ContentView() }

// Display a fully immersive space. ImmersiveSpace(id: "solarSystem") { SolarSystemView() }.immersionStyle(selection: $currentStyle, in: .mixed, .progressive, .full) }}
复制代码

风格适配

既然 app 是在 Vision Pro 的空间中展示,那么最好可以遵循 Vision Pro 统一的样式风格,比如:


圆角,毛玻璃半透明的背景



悬停效果



这里说一下悬停效果,它指的是眼睛停留在某个 UI 元素上时的效果。如果不进行适配,在 Vision Pro 上运行 app,眼睛看向一个可以点击的元素时,它会被高亮显示:



但是苹果似乎觉得这样简单粗暴的悬停效果不够高雅,所以提供了 hoverEffect 属性让我们可以自定义悬停效果:



这样设置后,眼睛停留在元素上时,我们可以实现高亮、突出、改变圆角等效果,而且高亮点会随着眼睛盯的点而改变,非常神奇。

超出边界外布局

在 visionOS app 中,为了提高场景的沉浸感,苹果允许把导航栏、tab 栏和工具栏等内容无关的元素设置到界面外,并且给他们起了一个独特的名字:ornament。使用系统自带的 UIHostingOrnament:



当然也可以自定义,将原来的导航栏等元素改造成 ornament:


改造前


struct ContentView: View {    @State private var selection: AppScreen = .backyards    var body: some View {            NavigationSplitView {            AppSidebarList(selection: $selection)        } detail: {            AppDetailColumn(screen: selection)}
复制代码


改造后


struct ContentView: View {    @State private var selection: AppScreen = .backyards    var body: some View {            View()            .ornament(visibility: isGoalPanelVisible,                      attachmentAnchor: .scene(.bottom),                      contentAlignment: .center) {                NavigationSplitView {                    AppSidebarList(selection: $selection)                } detail: {                    AppDetailColumn(screen: selection)                }            }    }}
复制代码

添加 3D 模型

visionOS 使用了苹果布局多年的 RealityKit,结合 SwiftUI,从而使得加载 3D 和 2D 模型就像加载一张本地资源图片一样方便:


struct SphereView: View {    @State private var scale = false

var body: some View { RealityView { content in if let earth = try? await ModelEntity(named: "earth") { content.add(earth) } } update: { content in if let earth = content.entities.first { earth.transform.scale = scale ? [1.2, 1.2, 1.2] : [1.0, 1.0, 1.0] } } .gesture(TapGesture().targetedToAnyEntity().onEnded { _ in scale.toggle() }) }}
复制代码


代码中 RealityView 就是专门用来展示模型资源的视图,就如同 UIImageView 加载图片一样,使用 ModelEntity 就可以很方便的加载本地的模型资源,并设置碰撞体积 CollisionComponent 和旋转缩放等等



需要注意的是苹果目前仅支持 USDZ 格式的模型,苹果给出了几个非常精美的模型资源以供下载:


https://developer.apple.com/cn/augmented-reality/quick-look/


另外我找到了几个可以免费下载 USDZ 格式资源的网站:


https://www.cgtrader.com/zh-cn/3d-models/ext/usdz


https://www.turbosquid.com/zh_cn/Search/3D-Models/usdz

与业务结合的实践

我们在进行实际业务场景适配的时候,如果是全新的 Vision Pro app,则首先要判断当前平台是否是 visionOS,如果是像我们一样基于 iPad app 进行改造,那么要判断是否是 iPad 设备,我们所采用的机型判断方法为:


func osType() {     if UIDevice.current.userInterfaceIdiom == .phone {         print("This code is running on iPhone")     } else if UIDevice.current.userInterfaceIdiom == .pad {         print("This code is running on iPad")     } else if UIDevice.current.userInterfaceIdiom == .vision {         print("This code is running on Vision Pro")     } }
复制代码


以我们零售 app 的适配设计为例,是基于 iPad app 进行改造,为了获得更好的展示效果,需要针对宽屏做 UI 改造:


iPhone 设计稿:



iPad 设计稿:



除了上文中提到的悬停效果等改造,资源位宽度,间距和排布等要素也需要进行相应的改变,来适配 iPad 或者 Vision Pro 更宽阔的视野。我们的 Feeds 展示场景,入口求部分氛围中配置的楼层背景图拉伸,并根据设计稿进行适配;为你推荐资源位一行二的展示样式改为为一行四,在用户使用时能够获得更好的视觉体验。


本篇暂时就先介绍到这里,后续会有更多 Vision Pro 适配和空间开发的文章,希望能帮助大家在即将到来的这场“空间计算战斗”先拔头筹。


作者:零售前台研发 姜海

来源:京东零售技术 转载请注明来源

发布于: 23 小时前阅读数: 18
用户头像

还未添加个人签名 2024-01-12 加入

京东零售那些事,有品、有调又有料的研发资讯,带你深入了解程序猿的生活和工作。

评论

发布
暂无评论
Vision Pro 开发实践(一)_人工智能_京东零售技术_InfoQ写作社区