RealityKit场景未持续调用System update(),仅移动Volume时生效
visionOS开发问题:立方体无法持续自动旋转
问题描述
在visionOS开发场景时,想要实现立方体持续旋转,已搭建场景并通过SpinSystem负责旋转更新。但在模拟器或头显中,前20次update会快速执行,之后逐渐停止,立方体不再旋转;只有拖动Volume手柄移动时,场景才会更新,立方体随之旋转。求实现无需交互Volume即可让立方体持续旋转的方法。
现有代码
import SwiftUI import RealityKit struct ContentView: View { var body: some View { VStack { RealityView { content in // 创建红色立方体实体 let cube = MeshResource.generateBox(size: [0.3, 0.3, 0.3]) let matl = SimpleMaterial(color: .red, isMetallic: false) let cubeEntity = ModelEntity(mesh: cube, materials: [matl]) cubeEntity.name = "cube" content.add(cubeEntity) // 注册"SpinSystem"系统来实现旋转 SpinSystem.registerSystem() } } } } // 用于逐帧旋转立方体的系统 class SpinSystem : System { var theta: Float = 0 var count: Int = 0 required init(scene: RealityFoundation.Scene) {} func update(context: SceneUpdateContext) { count += 1 print("update \(count)") if let cubeEntity = context.scene.findEntity(named: "cube") { theta += 0.01 cubeEntity.transform.rotation = simd_quatf(angle: theta, axis: simd_float3(1, 0, 0)) } } }
模拟器截图

日志输出
update 1 update 2 cannot add handler to 0 from 1 - dropping update 3 update 4 update 5 update 6 update 7 cannot add handler to 0 from 1 - dropping update 8 update 9 ... update 21 update 22 update 23
解决方案
原因分析
问题出在SpinSystem的注册逻辑和更新触发机制上:
- 仅调用
SpinSystem.registerSystem()只是注册系统类型,未将系统实例添加到场景的更新循环中; - 默认的
System更新触发条件不会强制持续更新,当场景无交互时,RealityKit会暂停非必要的更新以节省性能。
方案一:使用实体的scheduleUpdate方法(推荐)
直接给立方体实体添加持续更新任务,依赖RealityKit的内置更新循环,无需自定义System:
import SwiftUI import RealityKit struct ContentView: View { var body: some View { VStack { RealityView { content in // 创建红色立方体 let cube = MeshResource.generateBox(size: [0.3, 0.3, 0.3]) let matl = SimpleMaterial(color: .red, isMetallic: false) let cubeEntity = ModelEntity(mesh: cube, materials: [matl]) cubeEntity.name = "cube" content.add(cubeEntity) // 给实体添加持续更新任务,基于帧间隔计算旋转角度(保证速度稳定) cubeEntity.scheduleUpdate(for: .simulation) { entity, deltaTime in let rotationAngle = 0.5 * Float(deltaTime) entity.transform.rotation *= simd_quatf(angle: rotationAngle, axis: simd_float3(1, 0, 0)) } } } } }
方案二:修复自定义System的注册和更新触发
如果坚持使用自定义System,需要完成两个关键修改:
- 将System实例添加到场景中;
- 设置系统的
updateTrigger为.updateWhenSceneIsActive,确保场景活跃时持续更新。
修改后的代码:
import SwiftUI import RealityKit struct ContentView: View { var body: some View { VStack { RealityView { content in // 创建红色立方体 let cube = MeshResource.generateBox(size: [0.3, 0.3, 0.3]) let matl = SimpleMaterial(color: .red, isMetallic: false) let cubeEntity = ModelEntity(mesh: cube, materials: [matl]) cubeEntity.name = "cube" content.add(cubeEntity) // 注册系统类型并将实例添加到场景 SpinSystem.registerSystem() let spinSystem = SpinSystem(scene: content.scene) content.scene.addSystem(spinSystem) } } } } class SpinSystem : System { var theta: Float = 0 var count: Int = 0 required init(scene: RealityFoundation.Scene) {} // 设置更新触发条件:场景活跃时持续更新 static var updateTrigger: SystemUpdateTrigger { .updateWhenSceneIsActive } func update(context: SceneUpdateContext) { count += 1 print("update \(count)") if let cubeEntity = context.scene.findEntity(named: "cube") { theta += 0.01 cubeEntity.transform.rotation = simd_quatf(angle: theta, axis: simd_float3(1, 0, 0)) } } }
说明
- 方案一的
scheduleUpdate更简洁,且自动适配RealityKit的更新机制,不会出现休眠问题; - 方案二中的
.updateWhenSceneIsActive会强制系统在场景处于活跃状态时每帧执行更新,避免无交互时暂停。
内容的提问来源于stack exchange,提问作者serious_tim
相关产品推荐
相关产品推荐

