runBlock发生后,在SKAction.sequence中延迟下一个动作(Swift)?

时间:2015-03-10 06:24:28

标签: ios swift sprite-kit

duration内部时,moveTo的{​​{1}}属性未被跟踪,允许序列中的后续操作立即执行,只应在{{1}之后执行秒。

代码A(序列正确执行):

runBlock

代码B(序列未正确执行):

duration

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() }])) 中,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() }])) 完成后Code A被删除(约2秒)。这是正确的顺序。

itemB中,moveActionCode B完成之前被移除,这意味着itemB永远不会从其原始位置移动。好像badMoveAction中没有遵守持续时间属性。

我们如何在itemB中移动Code B,但确保序列中的下一个操作在itemB完成之前不会开始?

6 个答案:

答案 0 :(得分:8)

这应该做你想要的。我只是重新安排了一些代码。

itemB.runAction(SKAction.sequence([

    // wait for half a second
    SKAction.waitForDuration(0.5),
    SKAction.runBlock({

        // after waiting half a second, get itemA's position
        let realDest = CGPointMake(itemA.position.x, itemA.position.y)
        let moveAction = SKAction.moveTo(realDest, duration: 2.0)

        // move to that position, after we get there, remove itemB from scene
        itemB.runAction(moveAction, completion: {
            itemB.removeFromParent()
        })

    })
]))

答案 1 :(得分:2)

<强>说明: 执行代码块时,它将异步执行。这意味着代码将在单独的队列中执行,而其余代码将继续执行。

对于代码A ,这不会导致问题,因为moveTo操作在当前队列上运行,已完成,然后触发runBlock。

代码B 的情况下,这会产生一个问题,因为badMoveAction块被触发,它开始在一个单独的队列上执行,代码继续执行下一个恰好是删除操作的部分删除itemB,而badMoveAction在后台执行。如果你在runBlock中做了其他事情,你会看到它们同时运行,但是因为你删除了它,一切都被删除了。

<强>解决方案 如果您要将badMoveAction添加到节点,并在每次执行此类操作时进行计算:

let waitAction = SKAction.waitForDuration(0.5)
let removeAction = SKAction.removeFromParent()

let sequence = SKAction.sequence([waitAction, moveAction(), removeAction])

func moveAction() -> SKAction {
    let realDest = CGPointMake(itemA.position.x, itemA.position.y)
    let moveAction = SKAction.moveTo(realDest, duration:2.0)
    return moveAction()
}

*代码只是您可以采取的措施来解决此问题。

答案 2 :(得分:2)

您可以尝试其他解决方案:

itemB.runAction(SKAction.waitForDuration(0.5)) {
     let realDest = CGPointMake(itemA.position.x, itemA.position.y)
     let moveAction = SKAction.moveTo(realDest, duration: 2.0)
     itemB.runAction(moveAction) {
         itemB.removeFromParent()
     }
}

runAction函数中的尾随闭包是一个完成块。

答案 3 :(得分:1)

您需要更改runAction的来电者。使用self进行调用。由于您使用的是runBlock并且您说parasite在其中运行了操作,因此无需在parasite上调用该函数。所以这样称呼它:

self.runAction(SKAction.sequence([SKAction.waitForDuration(0.5), moveParasite]))

答案 4 :(得分:1)

根据文档,runBlock立即执行,并且不遵守moveTo的持续时间。 代码A 代码B 的排序是正确的,但在后一种情况下,似乎它不按顺序排列,因为moveTo()持续时间不受尊重

作为运行代码块导致一个或多个操作的问题的解决方案,同时尊重持续时间,请尝试以下代码:

func notSoBadMoveAction() -> SKAction {
    let realDest = CGPointMake(itemA.position.x, itemA.position.y)
    let moveAction = SKAction.moveTo(realDest, duration: 2.0)
    return moveAction
}

itemB.runAction(SKAction.sequence([   
   SKAction.waitForDuration(0.5), 
   notSoBadMoveAction(), 
   SKAction.runBlock {
       itemB.removeFromParent()
   }]))

此代码确实使用了移动的完整持续时间,它可以替换runBlock的一些(但可能不是所有其他)其他用途。如果您愿意,该函数也可以采用参数,因此可以生成更常见的生成操作的情况。

ADDITION:以下是该功能的替代版本,显示添加操作的可能性,并计算函数内的内容:

func myMoveAction(pos: CGPoint, duration : NSTimeInterval) -> SKAction {
    let realDest = CGPointMake(pos.x, pos.y)
    let moveAction = SKAction.moveTo(realDest, duration: duration/4)
    let moveAction2 = SKAction.moveTo(CGPointMake(realDest.x/2, realDest.y/2), duration: duration * 2/4)
    let moveAction3 = SKAction.moveTo(realDest, duration: duration/4)
    return SKAction.sequence([moveAction, moveAction2, moveAction3])
}

答案 5 :(得分:0)

SKAction.runBlock的有效期为0.0。幸运的是,duration属性是可变的。

badMoveAction.duration = 2.0应该将块延迟足够长的时间,以便在块内的操作完成后运行。