The duration
property for moveTo
isn't followed when inside a runBlock
, allowing the subsequent action in a sequence to get executed immediately when it should only get executed after duration
seconds.
Code A (sequence properly executed):
let realDest = CGPointMake(itemA.position.x, itemA.position.y)
let moveAction = SKAction.moveTo(realDest, duration: 2.0)
itemB.runAction(SKAction.sequence([SKAction.waitForDuration(0.5), moveAction, SKAction.runBlock {
itemB.removeFromParent()
}]))
Code B (sequence not properly executed):
let badMoveAction = SKAction.runBlock {
let realDest = CGPointMake(itemA.position.x, itemA.position.y)
let moveAction = SKAction.moveTo(realDest, duration: 2.0)
itemB.runAction(moveAction)
}
itemB.runAction(SKAction.sequence([SKAction.waitForDuration(0.5), badMoveAction, SKAction.runBlock {
itemB.removeFromParent()
}]))
In Code A
, itemB
gets removed after the moveAction
completes (about 2 seconds). This is the correct sequence.
In Code B
, itemB
gets removed before badMoveAction
finishes, meaning itemB
never moves from its original position. It's as if the duration property isn't honored in Code B
.
How can we move itemB
as in Code B
but ensure the next action in the sequence doesn't start until badMoveAction
completes?
runBlock
ofSKAction
creates action with zero duration and it takes place instantaneously. So inCode B
it will start executing first action and return immediately to start next action in sequence.If you want to create your own action with duration you can use
customActionWithDuration:actionBlock:
. Otherwise hereCode A
is perfectly fine(if you want to use move action only).Also you can use
SKAction.removeFromParent()
to removeitemB
instead of:Other solution:
As
runBlock
executes immediately you can addwaitForDuration
action before removing node.(add after runBlock with duration equal to runBlock)But this can be achieved using
customActionWithDuration:actionBlock:
.If you want both action(move, remove node) should occur simultaneously then you can also use
group
in SKAction.