深化并拓宽你的visionOS运用,并探究如何将你的运用内容整合到用户的环境中。

概述

配备立体显现的设备让人们以更真实的办法体会3D内容。内容呈现出真实的深度,人们能够从不同的角度观看,使其看起来就像在他们面前一样。

当为visionOS构建运用时,考虑你或许会如何增加运用界面的深度。体系供给了多种显现3D内容的办法,包括在你现有的窗口中、在体积中和在沉溺式空间中。挑选最适合你的运用和你供给的内容的选项。

VisionOS文档翻译与实践3-向你的应用添加3D内容

窗口

VisionOS文档翻译与实践3-向你的应用添加3D内容

空间容器元素(volume)

VisionOS文档翻译与实践3-向你的应用添加3D内容

沉溺式空间(immersive space)

在传统的2D窗口中增加深度

窗口是运用界面的重要部分。对于visionOS,运用主动取得具有visionOS外观和感觉的材质,彻底可调整巨细的窗口,以及用于你的自界说操控的高亮度调整。

视频

在需求的时候,将深度效果整合到你的自界说视图中,并运用3D布局选项来在你的窗口中摆放视图。

  • 运用shadow(color:radius:x:y:)或visualEffect(_:)修改器到视图上。
  • 当有人看向视图时,运用hoverEffect(_:isEnabled:)修改器来提高或杰出视图。
  • 运用ZStack来布局视图。
  • 运用transform3DEffect(_:)来动画化与视图相关的改动。
  • 运用rotation3DEffect(_:axis:anchor:anchorZ:perspective:)修改器来旋转视图。

除了给2D视图增加更多的深度外,你还能够将静态3D模型增加到你的2D窗口中。Model3D视图加载USDZ文件或其他财物类型,并在你的窗口中以其内涵巨细显现。在你已经在运用中有模型数据,或能够从网络上下载的当地运用这种视图。例如,购物运用或许运用这种视图来显现产品的3D版本。

运用RealityKit展现动态3D场景

RealityKit是苹果用于构建你能够在屏幕上动态更新的3D模型和场景的技术。在visionOS中,运用RealityKit和SwiftUI一同将你的运用的2D和3D内容无缝地结合在一同。加载现有的USDZ财物,或许在Reality Composer Pro中创立包括动画、物理、光照、声音和你的内容的自界说行为的场景。要在你的运用中运用Reality Composer Pro项目,将Swift包增加到你的Xcode项目中,并在你的Swift文件中导入其模块。有关详细信息,请参阅在你的Xcode项目中管理文件和文件夹。

VisionOS文档翻译与实践3-向你的应用添加3D内容

当你准备在你的界面中展现3D内容时,运用RealityView。这个SwiftUI视图作为你的RealityKit内容的容器,并答应你运用了解的SwiftUI技术更新那些内容。

以下示例展现了一个运用RealityView显现3D球体的视图。视图闭包中的代码为球体创立一个RealityKit实体,将纹理运用到球体的表面,并将球体增加到视图的内容中。

struct SphereView: View {
    var body: some View {
        RealityView { content in
                     let model = ModelEntity(
                mesh: .generateSphere(radius: 0.1),
                materials: [SimpleMaterial(color: .white, isMetallic: true)])
                     content.add(model)
                    }
    }
}

当SwiftUI显现你的RealityView时,它只履行一次你的代码以创立实体和其他内容。由于创立实体相对贵重,所以视图只运转一次你的创立代码。当你想要更新你的实体的状况时,改动你的视图的状况,并运用一个更新闭包来将这些改动运用到你的内容中。下面的示例运用一个更新闭包来改动球体的巨细,当scale特点的值改动时:

struct SphereView: View {
    @State var scale = false
    var body: some View {
        RealityView { content in
                     let model = ModelEntity(
                mesh: .generateSphere(radius: 0.1),
                materials: [SimpleMaterial(color: .white, isMetallic: true)])
                     content.add(model)
                    } update: { content in
                   if let model = content.entities.first {
                model.transform.scale = scale ? [1.2, 1.2, 1.2] : [1.0, 1.0, 1.0]
            }
                  }
    }
}

关于如何运用RealityKit创立内容,请拜见RealityKit。

响应与RealityKit内容的交互

要处理与你的RealityKit场景的实体的交互:

将手势辨认器附加到你的RealityView并增加targetedToAnyEntity()修改器到它。

将InputTargetComponent附加到实体或其父实体之一。

增加磕碰形状到支撑交互的RealityKit实体。

targetedToAnyEntity()修改器为手势辨认器和你的RealityKit内容供给了一个桥梁。例如,要辨认当有人拖动实体时,指定一个DragGesture。

然后将onChanged(_:)onEnded(_:) 修改器附加到手势以响应交互。下面的示例为RealityView增加一个拖动手势,它改动了offset状况的值:

struct DraggableView: View {
    @GestureState var offset: SIMD3<Float> = [0, 0, 0]
    var body: some View {
        RealityView { content in
                     let model = ModelEntity(
                mesh: .generateSphere(radius: 0.1),
                materials: [SimpleMaterial(color: .white, isMetallic: true)])
                     model.components[InputTargetComponent.self] = InputTargetComponent()
                     content.add(model)
                    } update: { content in
                   if let model = content.entities.first {
                model.transform.translation += offset
            }
                  }
        .gesture(
            DragGesture()
            .updating($offset, body: { (value, state, _) in
                                          state = [Float(value.translation.width), -Float(value.translation.height), 0]
                                         })
            .onEnded({ _ in
                          self.offset = [0, 0, 0]
                         })
        )
    }
}

在这个例子中,DragGestureupdating(_:, body:) 修改器在拖动手势改动时更新offset状况。当拖动手势结束时,onEnded(_:) 修改器重置offset状况为原始值。

为支撑交互的RealityKit实体增加磕碰形状。磕碰形状界说了实体的物理形状,并答应RealityKit正确地处理与实体的交互。在创立你的实体时,运用generateCollisionShapes(recursive:) 函数来主动为你的实体和其所有子实体生成磕碰形状。

请注意,你能够运用SwiftUI的 @GestureState特点来跟踪手势的状况,然后在你的update闭包中运用这个状况来更新你的RealityKit实体。

为了更深入地了解如何在你的运用中运用RealityKit,能够参阅RealityKit文档。

在空间容器元素中显现3D内容

空间容器元素是一种窗口类型,其在三个维度上增加以匹配其所包括的内容巨细。窗口和空间容器元素都能够容纳2D和3D内容,而且在许多方面都类似。然而,窗口会裁剪超出窗口表面的3D内容,所以对于主要是3D的内容,空间容器元素是更好的挑选。

创立空间容器元素,需求在你的运用中增加一个WindowGroup场景,并将其款式设置为空间容器元素款式。这种款式告知SwiftUI创立一个用于3D内容的窗口。在你的空间容器元素中包括任何你想要的2D或3D视图。你也能够增加一个RealityView来运用RealityKit构建你的内容。下面的示例创立了一个空间容器元素,其间包括存储在运用程序包中的一些气球的静态3D模型:

struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            Model3D("balloons")
        }.windowStyle(style: .volumetric)
    }
}

窗口和空间容器元素是显现有界2D和3D内容的便捷办法,但是你的运用并不能操控那些内容在人的环境中的方位。体系在显现时间设置每个窗口和体积的初始方位。体系还增加了一个窗口条,以便人们从头定位窗口或调整其巨细。

对于何时运用体积的更多信息,请拜见人机接口指南 > 窗口。

在人的环境中显现3D内容

当你需求对你的运用内容的方位有更多的操控时,将那些内容增加到一个沉溺式空间。沉溺式空间供给了一个无边界的区域用于你的内容,而且你能够操控空间内内容的巨细和方位。在得到用户的许可后,你还能够运用ARKit与沉溺式空间一同,将内容融入他们的环境。例如,你能够运用ARKit场景重建获取家具和邻近物体的网格,并让你的内容与该网格进行交互。

沉溺式空间是你创立的与运用的其他场景相同的场景类型。以下示例显现了一个运用,该运用包括一个沉溺式空间和一个窗口:

@main
struct MyImmersiveApp: App {
    var body: some Scene {
        WindowGroup() {
            ContentView()
        }
        ImmersiveSpace(id: "solarSystem") {
            SolarSystemView()
        }
    }
}

假如你不在你的ImmersiveSpace声明中增加一个款式修饰符,体系会运用混合款式创立该空间。这种款式将你的内容与显现人的环境的透视内容一同显现。其他款式让你能够在不同程度上躲藏透视内容。运用immersionStyle(selection:in:) 修饰符来指定你的空间支撑的款式。假如你指定了多种款式,能够运用修饰符的挑选参数在款式之间切换。

正告:

请注意你在运用混合款式的沉溺式场景中包括的内容有多少。即使那些内容部分透明,也能填满屏幕的一大部分,这或许会阻止人看到他们环境中的潜在风险。假如你想让人沉溺在你的内容中,运用彻底款式装备你的空间。更多信息,请拜见,创立运用中的全沉溺式体会。

记得设置你在ImmersiveSpace中放置的项目的方位。运用修饰符设置SwiftUI视图的方位,并运用其变换组件设置RealityKit实体的方位。SwiftUI最初在人的脚下设置空间的原点,但能够响应其他事件更改此原点。例如,体系或许会移动原点以习惯运用空间化角色显现你的内容的SharePlay活动。假如你需求将SwiftUI视图和RealityKit实体相对于互相定位,运用RealityView内容参数中的办法进行所需的坐标转化。

要显现你的ImmersiveSpace场景,运用从SwiftUI环境获取的openImmersiveSpace动作来翻开它。此动作异步运转,并运用供给的信息查找并初始化你的场景。以下示例显现了一个翻开带有solarSystem标识符的空间的按钮

Button("Show Solar System") {
    Task {
        let result = await openImmersiveSpace(id: "solarSystem")
        if case .error = result {
            print("An error occurred")
        }
    }
}

当运用展现ImmersiveSpace时,体系会躲藏其他运用的内容以防止视觉冲突。当你的空间可见时,其他运用保持躲藏,但当你封闭它时,它们会回来。假如你的运用界说了多个空间,你必须先封闭当时可见的空间,然后才能显现不同的空间。假如你没有封闭可见的空间,当你企图翻开其他空间时,体系会发出运转时正告。