1470 字
7 分钟
Vision OS 介绍
2023-09-27
无标签

设备/系统介绍#

硬件#

  • Optic - 生物认证
  • 很多摄像头和传感器 - 手部动作识别
  • 眼球追踪 - 改变焦点
  • 机身旋钮 - 开启/关闭沉浸度
  • 机身两侧喇叭 - 放声音,支持空间音频;机身前方显示屏 - 装饰用。。。

性能:M2 + R1

交互方式#

窗口/控件/物体#

要操控窗口/控件/物体,交互方式是:看着一个物体/控件,然后做手势

SwiftUI默认支持的动作类型:

  • 手指捏合一下(点击)
  • 双手捏合并旋转(旋转)
  • 手指捏合然后移动(拖拽)

其他的动作,需要使用ARKit去自定义手部动作识别。

输入#

  • 虚拟键盘

(手指点在虚拟按键上完成输入?还是用上面跟控件的交互方式?目前不清楚)

  • 接入苹果支持的键盘使用。候选框在实体键盘附近展示。
  • 手柄

系统#

VisionOS

  • VisionPro能感知人体的移动,虚拟的物体/窗体像是被固定在现实世界一样
  • VisionPro会给房间建模、获取房间的光照信息,以显示虚拟窗体的阴影效果
  • 同一个视角,可以同时显示多个窗口(当然也可以同时显示多个APP)。

构建一个Vision APP#

Scene#

iOS APP里的View是2D的。为了让View做到3D显示,苹果在View上加了一层Scene的概念,用于定义View的展示效果。

从展示效果上区分:

  • Window:主要用于展示平面元素、2D窗体
  • Volume:用于展示三维物体
  • Immersive Space:沉浸空间,啥都可以展示

Window#

平面窗体类型,展示2D元素为主。

方向轴(假设用户面朝一个窗体):

往右:X轴

往下:Y轴

往用户方向:Z轴

  • Window有一定的Z轴空间,但不能人为调整Z轴的大小
  • Window的大小可随用户调整(可以设置最大/最小的大小)

Volume#

  • Z轴指向用户
  • 独立的3D窗口,主要用于呈现3D模型,可以同时打开多个
  • 开发人员可以调整大小
  • 用户不可以调整大小,只能调整位置

Immersion Space#

沉浸式空间。可以放Volume或Window。

同一时间只能打开一个Immersive Space。打开Immservice Space时,其他APP的内容会被隐藏。

可以改变的沉浸类型:

  • full - 纯VR展示,用户看到的全是虚拟的内容
  • mix - 纯MR展示
  • progressive - 半MR半VR,通过旋钮调整程度

  • 原点在用户的脚上。
  • 每个物体有自身的坐标轴。Swift提供了transform方法,将两种坐标轴统一放在ImmserviceSpace中做转换,解决Window和Volume坐标轴不同的问题

相关代码#

定义Scene#

在API上,苹果偷偷改了immersionStyle的modifier,现在不再以枚举变量区分沉浸类型,改为类似密封类的形式做区分。

控制Scene#

引入相关环境变量

@Environment(\.openWindow) var openWindow // 根据id打开窗口
@Environment(\.dismissWindow) var dismissWindow // 根据id关闭窗口
@Environment(\.openImmersiveSpace) var openImmersiveSpace // 根据id打开沉浸空间
@Environment(\.dismissImmersiveSpace) var dismissImmersiveSpace // 关闭当前打开的沉浸空间

上面所有的方法都是异步的。

Ornaments#

一个modifier,用于在窗体附近显示View

可用于:播放器进度条、快捷开关、快捷tab切换

跟overlay的区别:

  • overlay作用在view上,ornament作用在window上(view的大小可能会和window不一致)

一些有用的Modifier#

作用在WindowGroup:

  • .windowResizability - 设置窗体被调整时的大小范围
    • contentSize - 由View的frame属性确定大小最大值、最小值
    • contentMinSize - 由View的frame属性确定大小最小值,不设置最大值
    • automatic - 系统默认,settings view用`contentSize`,其他用`contentMinSize`
  • .windowStyle - scene类型,上面有
  • .defaultSize - 窗体默认大小,支持调整长、宽、高、单位

作用在View:

  • .padding3D - 支持三维的.padding
  • .frame(depth) - 支持三维的frame,设置z轴长度

作用在ImmsersiveSpace:

  • .immersionStyle - 沉浸程度
  • .defaultSize - 默认大小

RealityView#

基本使用#

  • E Entity - 一个载入的模型
  • C Component - 给Entity添加不同的能力
    • InputTargetComponent - 接受输入
    • CollisionComponent - 计算碰撞体积
  • S System - 整个系统,包含多个Entity,在每一帧显示前会通知外界(外界从这里动态调整Entity的属性)

Entity的初始化在make闭包中完成,每一帧的更新会回掉update闭包。

举个例子

加载模型#

let entity = try? await Entity(named: "test")
let entity2 = try? await Entity(named: "test2", in: realityKitContentBundle)

播放动画#

流程:定义动画类型 => 创建动画元素 => Entity播放动画

播放模型动画:

下面Demo为了直观,直接用强制非空取代空判断;实际开发中必须要做判空。

let entity = try! await Entity(named: "test")
let def = entity.availableAnimations[0].definition // 定义动画类型
let ani = try! AnimationResource.generate(with: AnimationView(source: def)) // 创建动画元素
entity.playAnimation(ani.repeat(count: 100)) // Entity播放动画

播放内置动画:

内置动画默认有FromToBy、Orbit、Sampled三种

  • FromToBy => CABasicAnimation
  • Sampled => CAKeyframeAnimation
  • Orbit => 环绕动画
let entity = try! await Entity(named: "test")
let def = OrbitAnimation(...) // 改了这行,定义动画类型
let ani = try! AnimationResource.generate(with: AnimationView(source: def)) // 创建动画元素
entity.playAnimation(ani.repeat(count: 100)) // Entity播放动画

手势#

用法:.onGesture(…)

与2D的SwiftUI相比,这里多了个targetedAnyEntity方法,意思是System内的所有Entity都能被这个gesture响应。

  • targetedAnyEntity - System内任意Entity都响应该手势
  • targetedToEntity(_ entity: Entity) - 指定Entity响应该手势
  • targetedToEntity(where query: QueryPredicate) - 指定某些Entity进行

移植#

APP直接在VisionOS上使用#

iOS上的APP可直接在VisionOS上使用,但无法表现VisionOS特有的UI效果,只能展示成一个普通的平面

移植公共逻辑类#

视图只能用SwiftUI写(是否能用OC,有待探究)

不可用的API#

  • Core Motion services
  • Barometer and magnetometer data
  • All location services except the standard service
  • HealthKit data
  • Video or still-photo capture
  • Camera features like auto-focus or flash
  • Rear-facing (selfie) cameras
Vision OS 介绍
https://blog.nowcent.cn/posts/dev/vision-os-介绍/
作者
orangeboy
发布于
2023-09-27
许可协议
CC BY-NC-SA 4.0