CAKeyframeAnimation执行后SCNNode位置值未更新问题求助
问题原因与解决方案
这是Core Animation动画的典型特性——它默认只修改节点的视觉渲染表现,不会同步更新节点的实际属性值。
Core Animation采用「动画与模型分离」的设计:当你给SCNNode添加CAKeyframeAnimation时,动画只是在渲染层(presentation layer)绘制了节点移动的效果,但节点本身的模型层(也就是你直接访问的fishNode.position)并不会被修改,所以无论动画怎么动,你读取的position值始终是初始值。
下面给你两种可行的解决思路:
1. 手动同步动画结束后的节点位置
如果你坚持使用CAKeyframeAnimation,可以在动画完成后手动把节点的position更新到动画的最终关键帧位置。可以通过CATransaction的完成回调来实现:
// 假设你已经创建了CAKeyframeAnimation实例 let moveAnimation = CAKeyframeAnimation(keyPath: "position") moveAnimation.values = [/* 你的关键帧位置数组 */] moveAnimation.duration = 2.0 moveAnimation.fillMode = .forwards moveAnimation.isRemovedOnCompletion = false // 使用CATransaction添加完成回调 CATransaction.begin() CATransaction.setCompletionBlock { // 取动画的最后一个关键帧值,更新节点位置 if let finalPos = moveAnimation.values?.last as? SCNVector3 { self.fishNode.position = finalPos } } fishNode.addAnimation(moveAnimation, forKey: "fishMove") CATransaction.commit()
2. 改用SceneKit原生的SCNAction(更推荐)
SceneKit提供了自己的动画系统SCNAction,它是专门为SCNNode设计的,动画执行过程中会自动同步更新节点的属性值,动画结束后fishNode.position就是最终的位置,不需要手动同步。
比如创建关键帧移动动作的示例:
// 定义你需要的关键帧位置数组 let keyframePositions: [SCNVector3] = [ SCNVector3(0, 0, -0.5), SCNVector3(0.3, 0.2, -0.5), SCNVector3(0.3, -0.2, -0.5) ] // 创建关键帧移动动作 let keyframeMoveAction = SCNAction.moveByKeyframe( withPath: nil, positions: keyframePositions, durations: [1.0, 1.0], // 每个关键段的时长 timingFunctions: nil ) // 执行动作,可选添加完成回调 fishNode.runAction(keyframeMoveAction) { print("动画完成!当前节点位置:\(self.fishNode.position)") }
这样动画结束后,你直接读取fishNode.position就能得到最终的位置值了。
内容的提问来源于stack exchange,提问作者michael-martinez
相关产品推荐
相关产品推荐

