【问题标题】:Is there a way to chain SceneKit Animations?有没有办法链接 SceneKit 动画?
【发布时间】:2020-01-19 21:56:17
【问题描述】:

我正在寻找一种链接 SceneKit 动画的方法。

我正在向场景中添加 x 个节点,我想添加第一个节点,使其淡入,一旦它可见,然后我们转到下一个节点,直到所有节点都可见。所以我需要在我们开始第二个节点之前结束第一个节点上的动画。

显然,我尝试了一个带有 SCNActions 的 for 循环,但动画是批处理的,所以所有节点同时出现。

我不知道会添加多少节点,所以我无法制作序列。

处理此问题的最佳方法是什么?

编辑:

好的,我想如果我在将序列添加到暂停场景之前将其添加到节点(包括增加的等待间隔)

let sequence = SCNAction.sequence([.wait(duration: delay), .fadeIn(duration: 0.5)])
node.runAction(sequence)

然后,一旦添加了所有节点,我就会取消暂停场景,它会达到我正在寻找的效果。但这似乎很hacky。

有没有更好的办法?

【问题讨论】:

标签: swift scenekit


【解决方案1】:

暂停/取消暂停 - 嗯,是的,它有效,但感觉如果你开始做更多的事情,这可能会导致问题。

我喜欢 (James P) 的 completionHandler 路由。您可以使用此方法设置多个(和不同的)动画或动作。比如移动到 (5,0,0)、旋转、动画,当它到达那里时,再次调用它并移动到 (10,0,0),等等。

如果它们都以相同的方式工作,那么您可以使用计时器来完成,如果您正在寻找它,这会给您一些一致性。如果你走这条路线,请确保将计时器放在主线程中。

您还可以根据需要创建一些预定义的序列:

let heartBeat = SCNAction.sequence([
        SCNAction.move(to: SCNVector3(-0.5,  0.0, 0.80), duration: 0.4),
        SCNAction.unhide(),
        SCNAction.fadeIn(duration: 1.0),
        SCNAction.move(to: SCNVector3(-0.3,  0.0, 0.80), duration: 0.4),
        SCNAction.move(to: SCNVector3(-0.2,  0.2, 0.80), duration: 0.4),
        SCNAction.move(to: SCNVector3(-0.1, -0.2, 0.80), duration: 0.4),
        SCNAction.move(to: SCNVector3( 0.0,  0.0, 0.80), duration: 0.4),
        SCNAction.move(to: SCNVector3( 0.1,  0.5, 0.80), duration: 0.4),
        SCNAction.move(to: SCNVector3( 0.3, -0.5, 0.80), duration: 0.4),
        SCNAction.move(to: SCNVector3( 0.5,  0.0, 0.80), duration: 0.4),
        SCNAction.fadeOut(duration: 0.1),
        SCNAction.hide()
        ])

node.runAction(SCNAction.repeatForever(heartBeat))

【讨论】:

    【解决方案2】:

    我最终使用了一个计时器,我确实考虑过这个但无法让它工作,可能是因为我没有在主线程上做。

    这是我目前使用的代码,以防其他人在同一条船上。

    func animateNodesInTo(scene: SCNScene, withDuration: TimeInterval) {
    
            DispatchQueue.main.async {
                let nodes = scene.rootNode.childNodes
                let acion = SCNAction.fadeIn(duration: withDuration)
    
                Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in
                    let opaqueNode = nodes.first(where: {$0.opacity == 0})
                    opaqueNode?.runAction(acion)
    
                    if opaqueNode == nil {
                        timer.invalidate()
                    }
                }
            }
    
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-26
      • 1970-01-01
      • 1970-01-01
      • 2019-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多