使用SKAction移动时,SKCameraNode.position didSet不会被触发

时间:2017-01-11 21:28:52

标签: swift sprite-kit swift3 skaction skcameranode

我有一个SKCameraNode的简单子类,我称之为InteractiveCameraNode。现在它很简单:当相机的位置发生变化时,我需要发生一些事情。这是我做的:

class InteractiveCameraNode: SKCameraNode {
   // MARK: - Properties
   var enableInteraction = true
   var positionResponders = [(CGPoint, CGPoint) -> Void]()


   /// Calls every closure in the `positionResponders` array
   override var position: CGPoint {
      didSet {
         if enableInteraction {
            for responder in positionResponders {
               responder(oldValue, position)
            }
         }
      }
   }
}

由于相机移动时我可能会发生多种事情,因此我会在相机的位置发生变化时调用一系列闭包。到目前为止,除了didSet观察者如果我使用动作移动相机时没有被调用,一切都完美无缺。如果我在相机上使用约束使其跟踪节点然后通过动作移动该节点,则它可以正常工作。如果我用手移动相机,它会起作用。为什么它不适用于行动?

2 个答案:

答案 0 :(得分:1)

我之前的回答是不正确的100%..无论是什么导致我的回答是我的另一个错误,我道歉..我今天也学到了一些有用的东西:)

看起来你所看到的行为是A)一个bug或B)一些我不理解的Swift / SK的更深层机制。

这是一个适合我在游乐场工作的解决方法:

class Noder: SKSpriteNode {

  var myPosition: CGPoint = CGPoint.zero { didSet { print(position) } }

  func initialize(scene: SKScene) {
    isUserInteractionEnabled = true
    scene.addChild(self)
  }

  override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    position = touches.first!.location(in: self.scene!)
  }

  override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    print(self.position)
    run(.moveBy(x: -35, y: 0, duration: 0.5), completion: {
      self.myPosition = self.position
    })
  }
}

使用:

// In didmovetoview:
let node = Noder(color: .black, size: CGSize(width: 25, height: 25))
node.initialize(scene: self)

输出,显示实际位置已从某个操作更新didSet

  

(50.0,-118.0)
  (14.9999971389771,-118.0)

但这可能对你想要的东西来说太慢了,所以你最好每帧position手动设置myPositionupdate()(无论哪一个都适用于{{} 1}} lol ..)

(感谢此段感到困惑)。

另外,我想知道KVO是否可以在这里使用..我还没有使用过它们,但是CameraNode已经是一个NSObject ......可能需要考虑一下因为这可能是某种类型的错误...

答案 1 :(得分:0)

运行一个操作来改变调用Node子类的位置的操作不会设置其位置,不会调用属性观察器(在您的情况下为didSet),因此,您的代码是从未执行过。

  

在这种情况下,解决方案是使用SKSceneDelegate并比较   节点在两个回调中的位置。您保存节点的   update(_:for :)中的初始位置,该位置在开头   每一帧的位置,然后计算   didEvaluateActions(for:),在操作完成后被调用   评估。

Read more