如何在iOS 18中用SwiftUI实现RealityView立体AR显示
双屏AR显示在RealityView中失效的问题解决
问题描述
此前在Storyboard+Swift+SceneKit环境下成功实现适配VR Box的双屏AR显示效果,但切换到RealityView后功能失效:仅左侧AR画面正常,右侧画面静止且尺寸偏小。目标是在iPhone上实现双屏AR显示立方体,打造AR/XR视图。
原实现代码:
import SwiftUI import RealityKit struct ContentView : View { var body: some View { HStack (spacing: 0){ MainView() MainView() } .background(.black) } } struct MainView : View { @State var anchor = AnchorEntity() var body: some View { RealityView { content in let item = ModelEntity(mesh: .generateBox(size: 0.2), materials: [SimpleMaterial()]) content.camera = .spatialTracking anchor.addChild(item) anchor.position = [0.0, 0.0, -1.0] anchor.orientation = .init(angle: .pi/4, axis:[0,1,1]) // Add the horizontal plane anchor to the scene content.add(anchor) } } }
问题根源
- 重复空间追踪冲突:每个
MainView都独立设置content.camera = .spatialTracking,但iOS仅支持一个活跃的空间追踪相机实例,第二个RealityView无法获取有效追踪数据,导致画面静止。 - 布局未强制等分:两个RealityView默认尺寸计算未适配双屏场景,引发右侧画面尺寸偏小。
- 锚点状态不共享:两个视图使用各自独立的
AnchorEntity,无法保持双屏内容的同步性。
解决方案与修改代码
核心调整思路
- 父视图统一管理共享锚点和空间追踪上下文,确保双屏同步
- 为左右视图设置独立相机实体并添加双目偏移,模拟人眼间距
- 强制双屏等分布局,修正尺寸问题
修改后的完整代码:
import SwiftUI import RealityKit struct ContentView : View { // 共享锚点与空间追踪配置 @State private var sharedAnchor = AnchorEntity() @State private var trackingMode = RealityView.Camera.TrackingMode.continuous var body: some View { HStack(spacing: 0) { ARSubView(sharedAnchor: sharedAnchor, trackingMode: trackingMode, eyeOffset: -0.03) .frame(maxWidth: .infinity, maxHeight: .infinity) ARSubView(sharedAnchor: sharedAnchor, trackingMode: trackingMode, eyeOffset: 0.03) .frame(maxWidth: .infinity, maxHeight: .infinity) } .background(.black) .onAppear { // 父视图中统一创建立方体并绑定到共享锚点 let cube = ModelEntity(mesh: .generateBox(size: 0.2), materials: [SimpleMaterial()]) cube.position = [0.0, 0.0, -1.0] cube.orientation = .init(angle: .pi/4, axis: [0,1,1]) sharedAnchor.addChild(cube) } } } struct ARSubView: View { let sharedAnchor: AnchorEntity let trackingMode: RealityView.Camera.TrackingMode let eyeOffset: Float // 双目水平偏移量,模拟人眼间距 var body: some View { RealityView { content in // 添加共享锚点到当前视图场景 content.add(sharedAnchor) // 创建独立相机实体并设置偏移 let cameraEntity = CameraEntity() cameraEntity.camera = .init(projection: .perspectiveFieldOfView(.degrees(60))) cameraEntity.position = [eyeOffset, 0, 0] content.add(cameraEntity) // 绑定空间追踪到当前相机实体 content.camera = .entity(cameraEntity, trackingMode: trackingMode) } } }
关键修改说明
- 共享锚点:立方体与锚点在父视图中统一初始化,两个子视图复用同一锚点,保证双屏内容完全同步
- 独立相机实体:左右视图各创建专属相机,通过
eyeOffset设置水平偏移实现VR双目效果,同时绑定同一追踪模式,确保追踪数据同步 - 强制等分布局:用
frame(maxWidth: .infinity)让两个视图均分屏幕宽度,解决右侧画面尺寸偏小问题
内容的提问来源于stack exchange,提问作者Ostoura
相关产品推荐
相关产品推荐

