visionOS构建App常见问答:对实体、沉浸式空间、碰撞形状等概念见解
针对visionOS构建App
(映维网Nweon 2024年01月18日)自2023年7月建立Vision Pro开发者实验室以来,苹果一直在邀请世界各地的开发者参加活动,并积极回答大家关心的问题。
现在,苹果分享了开发者针对visionOS构建App时的常见问题答案,包括对实体、沉浸式空间、碰撞形状等新概念的重要见解。
1. 如何使用手势与实体交互?
实现基于手势的实体交互需要三个重要元素:
-
实体必须具有 InputTargetComponent。否则,它完全无法接收手势输入。
-
实体必须具有 CollisionComponent。碰撞组件的形状定义了手势实际可以击中的区域,因此请确保正确指定碰撞形状,以便与实体进行交互。
-
你使用的手势必须针对你尝试与之交互的实体 (或任何实体)。例如:
private var tapGesture: some Gesture { TapGesture() .targetedToAnyEntity() .onEnded { gestureValue in let tappedEntity = gestureValue.entity print(tappedEntity.name) } }
为交互式实体提供一个 HoverEffectComponent 也是不错的主意,这让系统能够在用户查看实体时触发标准的突出显示效果。
2. 我应该使用窗口组、沉浸式空间,还是两者皆用?
当你决定为 App 中的特定功能使用哪种场景类型时,请考虑窗口、空间容器和沉浸式空间之间的技术差异。
以下是一些重要的技术差异,请在做出决定时加以考虑:
-
当沉浸式空间打开时,用户打开的其他 App 的窗口和空间容器将被隐藏。
-
窗口和空间容器会裁剪超出其范围的内容
-
用户可以完全控制窗口和空间容器的放置。App 可以完全控制沉浸式空间中内容的放置。
-
空间容器具有固定大小,窗口可调整大小。
-
ARKit 仅在具有开放的沉浸式空间时才将数据传送到你的 App。
探索Hello World 示例代码,熟悉 visionOS 中每种场景类型的行为。
3. 如何可视化场景中的碰撞形状?
使用“调试可视化”菜单中的“碰撞形状”调试可视化;你还可以在该菜单中找到其他几个有用的调试可视化。有关调试可视化的信息,请查看诊断运行中的 App 出现的外观问题。
4. 可以将 SwiftUI 视图放置在沉浸式空间中吗?
当然可以!你可以使用 offset(x:y:) 和 offset(z:) 方法将 SwiftUI 视图放置在沉浸式空间中。请务必记住,这些偏移量是以点而非米为单位指定的。你可以利用 PhysicalMetric 将米转换为点。
5. 如果我想相对于现实视图中的实体定位 SwiftUI 视图,该怎么办?
使用 RealityView 附件 API 创建 SwiftUI 视图,并使其可作为 ViewAttachmentEntity 进行访问。该实体可以像任何其他实体一样定位、定向和缩放。
RealityView { content, attachments in // Fetch the attachment entity using the unique identifier. let attachmentEntity = attachments.entity(for: "uniqueID")! // Add the attachment entity as RealityView content. content.add(attachmentEntity) } attachments: { // Declare a view that attaches to an entity. Attachment(id: "uniqueID") { Text("My Attachment") } }
6. 可以通过编程来定位窗口吗?
没有 API 可用于定位窗口,但我们很乐意了解你的用例。请提交改进请求。有关本主题的更多信息,请查看定位和调整窗口大小。
7. 有没有办法知道用户在查看什么?
如采用隐私和用户偏好的最佳实践中所述,系统在处理摄像头和传感器输入时,不会直接将信息传递给 App。因此,并无方法可获得精确的眼球运动或确切的视线。相反,重点应是创建人们可以交互的界面元素,并让系统管理交互。如果你有一个无法以这种方式运作的用例,并且它不需要明显的眼球运动追踪,请提交改进请求。
8. visionOS 上何时调用 onHover 和 onContinuousHover 操作?
当手指悬停在视图上,或连接的触控板上的指针悬停在视图上时,将调用onHover和 onContinuousHover操作。
9. 可以在 App 中展示我自己的沉浸式环境纹理吗?
如果你的 App 打开了 ImmersiveSpace,则可以使用 UnlitMaterial 创建一个大球体,并将其缩放为内向式的几何体:
struct ImmersiveView: View { var body: some View { RealityView { content in do { // Create the sphere mesh. let mesh = MeshResource.generateSphere(radius: 10) // Create an UnlitMaterial. var material = UnlitMaterial(applyPostProcessToneMap: false) // Give the UnlitMaterial your equirectangular color texture. let textureResource = try await TextureResource(named: "example") material.color = .init(tint: .white, texture: .init(textureResource)) // Create the model. let entity = ModelEntity(mesh: mesh, materials: [material]) // Scale the model so that it's mesh faces inward. entity.scale.x *= -1 content.add(entity) } catch { // Handle the error. } } } }
10. 我已有立体视频,如何将其转换为 MV-HEVC?
AVFoundation 提供了 API,以编写 MV-HEVC 格式的视频。
要将视频转换为 MV-HEVC,请按以下步骤操作:
-
为左右视图各创建一个 AVAsset。
-
使用 AVOutputSettingsAssistant 获取适用于 MV-HEVC 的输出设置。
-
指定水平视差调整和视野 (特定于资源)。我们来看一个示例:
var compressionProperties = outputSettings[AVVideoCompressionPropertiesKey] as! [String: Any] // Specifies the parallax plane. compressionProperties[kVTCompressionPropertyKey_HorizontalDisparityAdjustment as String] = horizontalDisparityAdjustment // Specifies the horizontal FOV (90 degrees is chosen in this case.) compressionProperties[kCMFormatDescriptionExtension_HorizontalFieldOfView as String] = horizontalFOV
-
创建一个 AVAssetWriterInputTaggedPixelBufferGroupAdaptor 作为 AVAssetWriter 的输入。
-
为左右视频轨道各创建一个 AVAssetReader。
-
读取左右轨道,然后将匹配的样本附加到标记的像素缓冲区组适配器中:
// Create a tagged buffer for each stereoView. let taggedBuffers: [CMTaggedBuffer] = [ .init(tags: [.videoLayerID(0), .stereoView(.leftEye)], pixelBuffer: leftSample.imageBuffer!), .init(tags: [.videoLayerID(1), .stereoView(.rightEye)], pixelBuffer: rightSample.imageBuffer!) ] // Append the tagged buffers to the asset writer input adaptor. let didAppend = adaptor.appendTaggedBuffers(taggedBuffers, withPresentationTime: leftSample.presentationTimeStamp)
11. 如何在 visionOS 上的 RealityKit 中照亮场景?
你可以通过以下方式在 visionOS 上的 RealityKit 中照亮场景:
-
使用系统提供的自动照明环境,可根据真实环境对环境进行更新。
-
通过 ImageBasedLightComponent 提供自己的基于图像的照明。要查看示例,请创建一个新的 visionOS App,选择 RealityKit 作为沉浸式空间渲染器,然后选择 Full 作为沉浸式空间。
12. 我发现 visionOS 不支持 CustomMaterial。是否有方法可以创建具有自定义着色的材质?
你可以使用 Shader Graph 在 Reality Composer Pro 中创建具有自定义着色的材质。以这种方式创建的材质可以作为 ShaderGraphMaterial 供 App 访问,以便你可以动态更改代码中着色器的输入。
有关 Shader Graph 的详细介绍,请观看探索 Reality Composer Pro 中的材质。
13. 如何相对于设备的位置定位实体?
在 ImmersiveSpace 中,你可以使用 queryDeviceAnchor(atTimestamp:) 方法获取设备的完整转换。
更多关于visionOS开发的信息,请访问苹果官网。