In the documentation for SpriteKit, I found this:
Generally, actions do not call public methods on nodes. For example, if you want to subclass SKNode to respond to a move(to:duration:) action, you might consider overriding its position property to add a didSet observer.
class MovingNode: SKSpriteNode {
override var position: CGPoint {
didSet {
// code to react to position change
}
}
}
However, because a move action that's running on an instance of MovingNode (defined in the code listing above) doesn't set its position, the observer isn't invoked and thus, your code is never executed.
I find this to be very strange because if actions don't use someNode.position = newPosition
, then how does the position of the node change? Isn't it impossible to change the value of a property without calling its setter?
However, if you print the value of someNode.position
every frame, the new position is reflected. So, evidently, something is calling its setter. If it's not the SKAction
then what is? And whatever is, how is it bypassing the property observer?
Does anyone know what behind the scenes work SKAction
does to change the value of node properties without calling the setter?
You can achieve this behavior doing something like this:
class Node { // aka SKNode
private var _position = 0
public var position: Int {
get {
return _position
}
set {
_position = newValue
}
}
public func runAction(_ value: Int) {
_position = value
}
}
class ObservedNode: Node { // aka MovingNode
override var position: Int {
didSet {
print(position)
}
}
}
Then if you do this
let node = ObservedNode()
node.runAction(10)
print(node.position)
You can see the position changed, but you skip the didSet
observer
Remember run
runs directly inside the SKNode
with access to private values.