我有一个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
观察者如果我使用动作移动相机时没有被调用,一切都完美无缺。如果我在相机上使用约束使其跟踪节点然后通过动作移动该节点,则它可以正常工作。如果我用手移动相机,它会起作用。为什么它不适用于行动?
答案 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
手动设置myPosition
或update()
(无论哪一个都适用于{{} 1}} lol ..)
(感谢此段感到困惑)。
另外,我想知道KVO是否可以在这里使用..我还没有使用过它们,但是CameraNode已经是一个NSObject ......可能需要考虑一下因为这可能是某种类型的错误...
答案 1 :(得分:0)
运行一个操作来改变调用Node
子类的位置的操作不会设置其位置,不会调用属性观察器(在您的情况下为didSet
),因此,您的代码是从未执行过。
在这种情况下,解决方案是使用
SKSceneDelegate
并比较 节点在两个回调中的位置。您保存节点的 update(_:for :)中的初始位置,该位置在开头 每一帧的位置,然后计算didEvaluateActions(for:)
,在操作完成后被调用 评估。