細心的讀者會發現在在??Day1???和??Day2???的示例中我們使用的都是??WindowGroup?
?。
@main
struct visionOSDemoApp: App {var body: some Scene {WindowGroup {ContentView()}}
}
本節我們來認識在visionOS開發中會經常用到的另一個概念??ImmersiveSpace?
?。
沉浸式空間為內容提供了一個無界的區域,可在空間內控制內容的大小和擺放位置。在獲取用戶的授權后,我們還可以使用開啟了沉浸空間的ARKit來將內容集成到周遭環境中。例如,可以使用ARKit場景重建來獲取家具的網格(mesh)及其附近的對象,讓內容可以與網格進行交互。
首先我們需要創建一個??ViewModel.swift?
?文件用于進行內容的相關配置。
import SwiftUI
import RealityKit
import ARKit@MainActor class ViewModel: ObservableObject {private let session = ARKitSession()private let worldTracking = WorldTrackingProvider()private var contentEntity = Entity()func setupContentEntity() -> Entity {let box = ModelEntity(mesh: .generateBox(width: 0.5, height: 0.5, depth: 0.5))contentEntity.addChild(box)return contentEntity}func runSession() async {print("WorldTrackingProvider.isSupported: \(WorldTrackingProvider.isSupported)")print("PlaneDetectionProvider.isSupported: \(PlaneDetectionProvider.isSupported)")print("SceneReconstructionProvider.isSupported: \(SceneReconstructionProvider.isSupported)")print("HandTrackingProvider.isSupported: \(HandTrackingProvider.isSupported)")Task {let authorizationResult = await session.requestAuthorization(for: [.worldSensing])for (authorizationType, authorizationStatus) in authorizationResult {print("Authorization status for \(authorizationType): \(authorizationStatus)")switch authorizationStatus {case .allowed:breakcase .denied:// TODObreakcase .notDetermined:break@unknown default:break}}}Task {try await session.run([worldTracking])for await update in worldTracking.anchorUpdates {switch update.event {case .added, .updated:print("Anchor position updated.")case .removed:print("Anchor position now unknown.")}}}}
}
在??setupContentEntity?
??方法中,我們通過??ModelEntity?
??創建了一個模型實體,其中對??mesh?
??參數使用??MeshResource.generateBox?
?創建了一個立方體,可使用參數的說明如下:
- mesh: 定義模型幾何形狀的網格。
- materials: 定義模型外觀的材質資源。
- collisionShape: 定義合成碰撞開關的形狀資源集合。
- mass: 按公斤計的模型質量。
另一個異步方法??runSession?
??用于進行配置和授權的處理,其中包含兩個??Task?
?。
通常我們會創建一個??ImmersiveView?
?來顯示沉浸空間的效果,但本例我們都放到了入口文件中:
import SwiftUI
import RealityKit@main
struct visionOSDemoApp: App {@StateObject var model = ViewModel()var body: some SwiftUI.Scene {ImmersiveSpace {RealityView { content incontent.add(model.setupContentEntity())}.task{await model.runSession()}}}
}
注意因為這里導入了??RealityKit?
??,所以為避免歧義我們使用了??SwiftUI.Scene?
??,然后在主體內容中是一個??RealityView?
??,其中添加了我們在??ViewModel?
??中所創建的立方體,同時使用異步任務去執行授權部分的??runSession()?
?方法。
代碼部分就是這么多,但在運行應用前我們還要配置一下??Info.plist?
??文件,我們需要將??Preferred Default Scene Session Role?
??選項修改為??Immersive Space Application Session Role?
?:
這時運行應用就會看到本文前面顯示的效果,最后我們再來了解一個調試的工具,在代碼區下方點擊圖標即可打開Visualizations彈窗,通過顯示檢測到表面、遮擋和錨點等來輔助我們的開始,我們的示例圖片便是勾選了??Surfaces?
?之后的效果。
示例代碼:??GitHub倉庫??
其它相關內容請見??虛擬現實(VR)/增強現實(AR)&visionOS開發學習筆記??