SKAction.rotate无法作用于SKCameraNode的技术问题求助
问题原因与解决方案
嘿,我知道这个问题的症结所在了!你在update方法里每一帧都手动设置相机的position,这会和SKAction的旋转动作产生冲突——虽然理论上position和rotation是独立属性,但SpriteKit在处理相机这类特殊节点时,手动持续修改position会干扰动作队列对rotation的更新,导致旋转动作无法正常生效。而直接设置zRotation是瞬间修改属性,不受这个持续更新的影响,所以能正常工作。
下面是两种可行的解决方案:
方案一:用SKAction实现相机跟随(推荐)
把手动在update里更新相机位置的逻辑,换成一个重复执行的SKAction,这样相机的位置更新和旋转动作都会在SpriteKit的动作队列里处理,能完美兼容:
修改你的代码如下:
- 去掉
update方法里的followBall()调用,甚至可以直接删掉update方法。 - 在
didMove(to:)里添加相机跟随的动作:
override func didMove(to view: SKView) { // ball init and other stuff scene!.camera = cam // 用SKAction实现持续跟随 let followAction = SKAction.repeatForever(SKAction.run { [weak self] in guard let self = self else { return } self.cam.position.x = self.ball.position.x self.cam.position.y = self.ball.position.y + 100 }) cam.run(followAction, withKey: "followBall") }
- 优化触摸事件里的旋转动作,避免动作叠加:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { for touch in touches { let location = touch.location(in: self.cam) // 先移除之前的旋转动作,避免叠加 cam.removeAction(forKey: "rotate") let targetAngle: CGFloat = location.x < screen.width/2 ? .pi/8 : -.pi/8 let rotateAction = SKAction.rotate(toAngle: targetAngle, duration: 0.2) cam.run(rotateAction, withKey: "rotate") } } override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { cam.removeAction(forKey: "rotate") let resetRotateAction = SKAction.rotate(toAngle: 0, duration: 0.2) cam.run(resetRotateAction, withKey: "rotate") }
方案二:添加旋转状态标志(临时方案)
如果你不想改动跟随逻辑,可以添加一个标志位,在旋转期间暂停手动更新相机位置:
- 新增一个属性:
var isRotating = false
- 修改
update方法:
override func update(_ currentTime: TimeInterval) { if !isRotating { followBall() } }
- 更新触摸事件:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { for touch in touches { let location = touch.location(in: self.cam) isRotating = true let targetAngle: CGFloat = location.x < screen.width/2 ? .pi/8 : -.pi/8 let rotateAction = SKAction.sequence([ SKAction.rotate(toAngle: targetAngle, duration: 0.2), SKAction.run { self.isRotating = false } ]) cam.run(rotateAction) } } override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { isRotating = true let resetRotateAction = SKAction.sequence([ SKAction.rotate(toAngle: 0, duration: 0.2), SKAction.run { self.isRotating = false } ]) cam.run(resetRotateAction) }
不过这个方案有个缺点:旋转期间相机不会跟随球移动,体验可能不太好,所以更推荐第一种方案。
内容的提问来源于stack exchange,提问作者J. H.
相关产品推荐
相关产品推荐

