I want to be able to run multiple animations, one after another, in SceneKit. I've implemented a function which runs one animation like so:
fileprivate func animateMove(_ move: Move) {
print("Animate move started " + move.identifier)
// I am creating rotateNode
let rotateNode = SCNNode()
rotateNode.eulerAngles.x = CGFloat.pi
scene.rootNode.addChildNode(rotateNode)
// Then I am selecting nodes which I want to rotate
nodesToRotate = ...
// Then I am adding the nodes to rotate node
_ = nodesToRotate.map { rotateNode.addChildNode($0) }
SCNTransaction.begin()
SCNTransaction.animationDuration = move.animationDuration
SCNTransaction.completionBlock = {
rotateNode.enumerateChildNodes { node, _ in
node.transform = node.worldTransform
node.removeFromParentNode()
scene.rootNode.addChildNode(node)
}
rotateNode.removeFromParentNode()
print("Animate move finished " + move.identifier)
}
SCNTransaction.commit()
}
And then I've tried to run multiple serial animations like so:
func animateMoves(_ moves: [Move]) {
for (index, move) in moves.enumerated() {
perform(#selector(animateMove(_:)),
with: move,
afterDelay: TimeInterval(Double(index) * move.duration)
}
}
Everything is animating but the animations don't run in a serial manner. Animations start and finish in unpredictable time. Sample logs from debugger:
Animate move started 1
Animate move started 2
Animate move finished 1
Animate move finished 2
Animate move started 3
Animate move finished 3
I realise that my approach isn't the best, but only in that way I was able to achieve almost working animations.
I know that there is a SCNAction class available. Maybe I should make many actions within one transaction? If so, could someone explain to me how exactly SCNTransactions work and why the completion SCNTransaction's completion block fires in unpredictable time?
Try to use SCNAction.sequence():
class func sequence([SCNAction])
Creates an action that runs a collection of actions sequentially
let sequence = SCNAction.sequence([action1, action2, action3]) // will be executed one by one
let node = SCNNode()
node.runAction(sequence, completionHandler:nil)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With