如何修改RealityKit中运行的OrbitAnimation的Transform实现轨道缓慢拓宽?
实现OrbitAnimation运行中动态拓宽轨道的方法
要在OrbitAnimation运行过程中不停止动画,实现轨道缓慢拓宽(y轴偏移从1到2),核心思路是叠加两个独立动画:一个负责维持环绕运动,另一个专门逐步修改y轴偏移量,让两者效果同步生效。
方案一:叠加动画实现(推荐)
利用RealityKit的动画叠加能力,同时运行环绕动画和轨道拓宽动画,两者互不干扰且效果自动合并:
func startAnimation() { DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { // 1. 创建持续运行的环绕动画 let orbit = OrbitAnimation(duration: 10, axis: [0, 1, -5], startTransform: Transform(translation: [0, 1, 0]), bindTarget: .transform, repeatMode: .repeat) let orbitAnimation = try! AnimationResource.generate(with: orbit) // 2. 创建轨道拓宽动画:y轴偏移从1过渡到2,时长可按需调整 let expandAnimation = try! AnimationResource.generate(with: BasicAnimation( path: \.transform.translation.y, from: 1, to: 2, duration: 8 // 比如8秒完成拓宽,和环绕动画周期配合 )) // 3. 叠加播放两个动画,避免互相覆盖 dragonSphere!.addAnimation(orbitAnimation, forKey: "orbitAnimation") dragonSphere!.addAnimation(expandAnimation, forKey: "expandOrbitAnimation") } }
关键说明:
- 使用
addAnimation(_:forKey:)而非playAnimation,确保两个动画同时运行、效果叠加 - 环绕动画负责维持实体的轨道旋转(
repeatMode: .repeat保证持续运行) - 拓宽动画仅针对
transform.translation.y属性做线性过渡,精准控制轨道拓宽的速度和幅度
方案二:实时更新Transform(备选)
如果需要更灵活的进度控制,可通过CADisplayLink每帧计算并更新y轴偏移值,注意需保留环绕动画的旋转效果:
var displayLink: CADisplayLink? var elapsedTime: TimeInterval = 0 let totalExpandDuration: TimeInterval = 8 // 拓宽总时长 let startY: Float = 1 let endY: Float = 2 func startAnimation() { DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { // 启动环绕动画 let orbit = OrbitAnimation(duration: 10, axis: [0, 1, -5], startTransform: Transform(translation: [0, self.startY, 0]), bindTarget: .transform, repeatMode: .repeat) let orbitAnimation = try! AnimationResource.generate(with: orbit) self.dragonSphere!.playAnimation(orbitAnimation) // 启动实时更新的DisplayLink self.elapsedTime = 0 self.displayLink = CADisplayLink(target: self, selector: #selector(self.updateOrbitYOffset)) self.displayLink?.add(to: .main, forMode: .common) } } @objc private func updateOrbitYOffset() { guard let link = displayLink else { return } elapsedTime += link.duration // 完成拓宽后停止更新 if elapsedTime >= totalExpandDuration { link.invalidate() displayLink = nil return } // 计算当前y偏移的线性插值 let progress = Float(elapsedTime / totalExpandDuration) let currentY = startY + (endY - startY) * progress // 更新transform,保留环绕动画的旋转部分 var currentTransform = dragonSphere!.transform currentTransform.translation.y = currentY dragonSphere!.transform = currentTransform }
注意事项:
- 直接修改
transform时,RealityKit会自动合并动画产生的变换与手动设置的偏移,不会打断环绕动画 - 该方案适合需要动态调整拓宽节奏(比如根据交互改变速度)的场景
内容的提问来源于stack exchange,提问作者Jack Amoratis
相关产品推荐
相关产品推荐

