You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS 18中使用RealityView实现同步立体VR视图的问题

iOS 18中使用RealityView实现同步立体VR视图的问题

我懂你现在的困扰啦——左右两个RealityView里的白盒子,左边转得欢,右边却完全不动,根本没法形成立体VR该有的同步效果对吧?

问题根源

你代码里第二个RealityView用了box.clone(recursive: true),克隆出来的是一个完全独立的实体副本,和原box没有任何绑定关系。所以当你在rotateMe()里修改原box的旋转时,克隆体根本接收不到任何更新,自然就一动不动了。

解决方案:用共享状态同步两个视图

我们可以用SwiftUI的可观察对象(ObservableObject)来管理共享的旋转状态,让两个RealityView都监听这个状态的变化,从而同步更新各自的3D实体。下面是修改后的完整代码:

import SwiftUI
import RealityKit

// 管理共享旋转状态的类
class RotationManager: ObservableObject {
    @Published var rotation: simd_quatf = simd_quatf(angle: .pi / 4, axis: [0,1,1])
}

struct ContentView: View {
    // 创建共享的旋转管理器实例
    @StateObject private var rotationManager = RotationManager()
    @State private var rotateTimer: Timer?

    var body: some View {
        HStack(spacing: 0) {
            // 左侧VR视图
            RealityView { content in
                // 创建左侧的盒子实体
                let boxMesh = MeshResource.generateBox(size: 0.5)
                let whiteMaterial = SimpleMaterial(color: .white, isMetallic: false)
                let boxEntity = ModelEntity(mesh: boxMesh, materials: [whiteMaterial])
                let anchor = AnchorEntity()
                anchor.addChild(boxEntity)
                
                // 初始应用共享的旋转状态
                anchor.transform.rotation = rotationManager.rotation
                content.add(anchor)
                
                // 订阅旋转状态变化,同步更新左侧实体
                rotationManager.$rotation
                    .sink { newRotation in
                        anchor.transform.rotation = newRotation
                    }
                    .store(in: &content.subscriptions)
            }

            // 右侧VR视图
            RealityView { content in
                // 创建右侧的盒子实体(和左侧完全相同)
                let boxMesh = MeshResource.generateBox(size: 0.5)
                let whiteMaterial = SimpleMaterial(color: .white, isMetallic: false)
                let boxEntity = ModelEntity(mesh: boxMesh, materials: [whiteMaterial])
                let anchor = AnchorEntity()
                anchor.addChild(boxEntity)
                
                // 初始应用共享的旋转状态
                anchor.transform.rotation = rotationManager.rotation
                content.add(anchor)
                
                // 订阅旋转状态变化,同步更新右侧实体
                rotationManager.$rotation
                    .sink { newRotation in
                        anchor.transform.rotation = newRotation
                    }
                    .store(in: &content.subscriptions)
            }
        }
        .background(.black)
        .onAppear {
            // 5秒后启动旋转动画
            DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
                // 先清空可能存在的旧定时器
                rotateTimer?.invalidate()
                
                // 启动定时旋转
                rotateTimer = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true) { _ in
                    updateRotation()
                }
            }
        }
    }

    // 更新共享旋转状态的方法
    private func updateRotation() {
        // 计算当前旋转角度,每次增加0.01弧度
        let currentAngle = rotationManager.rotation.angle
        let newAngle = currentAngle + 0.01
        // 应用新的旋转到共享状态
        rotationManager.rotation = simd_quatf(angle: newAngle, axis: [0,1,0])
    }
}

关键修改点说明

  1. 共享状态管理:新增RotationManager类,用@Published标记旋转属性,确保状态变化时能通知所有订阅者。
  2. 双视图订阅状态:每个RealityView都创建自己的实体实例(不能共用同一个实体,因为每个RealityView有独立的场景),然后订阅rotationManager.rotation的变化,同步更新自身实体的旋转。
  3. 旋转逻辑迁移:把原来直接修改box的代码,改成修改共享的rotation属性,这样两个视图会自动同步更新。

这样修改后,左右两个盒子就会完全同步旋转,完美实现你想要的立体VR同步效果啦!

备注:内容来源于stack exchange,提问作者Ostoura

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 08:38:02