簡體   English   中英

SceneKit中的多個串行動畫

[英]Multiple serial animations in SceneKit

我希望能夠在SceneKit中一個接一個地運行多個動畫。 我已經實現了一個運行一個動畫的函數:

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()
}

然后我嘗試運行多個串行動畫,如下所示:

    func animateMoves(_ moves: [Move]) {
        for (index, move) in moves.enumerated() {
            perform(#selector(animateMove(_:)), 
            with: move, 
            afterDelay: TimeInterval(Double(index) * move.duration)
        }
    }

一切都是動畫,但動畫不是以連續的方式運行。 動畫在不可預測的時間內開始和結束。 來自調試器的示例日志:

Animate move started 1
Animate move started 2
Animate move finished 1
Animate move finished 2
Animate move started 3
Animate move finished 3

我意識到我的方法不是最好的,但只有通過這種方式,我才能實現幾乎可以工作的動畫。

我知道有一個SCNAction類可用。 也許我應該在一次交易中做出很多動作? 如果是這樣,有人可以向我解釋SCNTransactions究竟是如何工作的以及SCNTransaction的完成塊在不可預測的時間內完成的原因是什么?

嘗試使用SCNAction.sequence()

class func sequence([SCNAction])

創建一個按順序運行操作集合的操作

let sequence = SCNAction.sequence([action1, action2, action3]) // will be executed one by one

let node = SCNNode()
node.runAction(sequence, completionHandler:nil)

按照@Oleh Zayats的回答我試圖使用SCNAction.sequence(_ :)方法實現我的案例,但問題是我需要在每個完成的子操作之后觸發完成處理程序,以便能夠從中刪除節點rotationNode。

經過幾個小時的掙扎,我得到了一個非常好的解決方案,它就像一個魅力。

即:

我做了一個函數rotateAction,它看起來像這樣:

func rotateAction(with move: Move, from rotateNode: SCNNode) -> SCNAction {

    let preAction = SCNAction.run { (rotateNode) in
        // all the pre action setup like choosing nodes to rotate
    }

    let action = SCNAction.rotate(by: -move.angle, around: vector, duration: move.animationDuration)

    let postAction = SCNAction.run { (rotateNode) in
        // completion handler for each action 
    }

    return SCNAction.sequence([preAction, action, postAction])
}

然后我能夠編寫一個函數,以便能夠一個接一個地運行多個動畫:

func animateRotateMoves(_ moves: [Move]) {
    let rotateNode = SCNNode()
    scene.rootNode.addChildNode(rotateNode)

    var actions: [SCNAction] = []
    for move in moves {
        let action = rotateAction(with: move, from: rotateNode)
        actions.append(action)
    }
    actions.append(SCNAction.removeFromParentNode())
    let sequence = SCNAction.sequence(actions)
    rotateNode.runAction(sequence)
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM