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

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))
        }
    }
}

模拟器截图

VisionPro模拟器中旋转立方体的截图

日志输出

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的注册逻辑和更新触发机制上:

  1. 仅调用SpinSystem.registerSystem()只是注册系统类型,未将系统实例添加到场景的更新循环中;
  2. 默认的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,需要完成两个关键修改:

  1. 将System实例添加到场景中;
  2. 设置系统的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 15:27:41