2

我有一个简单的子类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如果我使用动作移动相机,观察者不会被调用。如果我在相机上使用约束使其跟踪节点,然后通过动作移动该节点,它就可以工作。如果我用手移动相机,它就可以工作。为什么它不适用于动作?

4

2 回答 2

1

我之前的回答是 100% 不正确的。无论导致我得到那个答案是我的其他错误,我很抱歉。我今天也学到了一些有用的东西 :)

看起来您看到的行为是 A)错误或 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)


但这对于你想要的可能太慢了,所以你最好手动设置positionmyPositionupdate()每一帧中设置(无论哪一个都适用于didSet大声笑..)

(这一段归功于 Confused)。


另外,我想知道 KVO 是否可以在这里工作。我没有使用它们,但 CameraNode 已经是一个 NSObject ......可能需要研究一下,因为这可能是某种错误......

于 2017-01-12T08:32:53.363 回答
0

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

SKSceneDelegate在这种情况下,解决方案是在两个回调中使用和比较节点的位置。您将节点的初始位置保存在 update(_:for:) 中,它在每帧开始时调用,然后计算位置的任何变化,在 didEvaluateActions(for:)评估动作后调用。

阅读更多

于 2019-01-02T18:48:36.853 回答