有没有办法链接 SceneKit 动画?

Posted

技术标签:

【中文标题】有没有办法链接 SceneKit 动画?【英文标题】:Is there a way to chain SceneKit Animations? 【发布时间】: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。

有没有更好的办法?

【问题讨论】:

您可以将runAction 与在操作完成时调用的completionHandler 结合使用。那会有帮助吗? developer.apple.com/documentation/scenekit/scnactionable/… 【参考方案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()
                
            
        

    

【讨论】:

以上是关于有没有办法链接 SceneKit 动画?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在 SceneKit 的 Collada 文件中存储动画数据或任意数据?

如何导出 DAE 文件以在 Scene Kit 中使用而不会看到“无标题动画”?

如何在我的 Scenekit.scene 之上创建 HUD

Swift SceneKit 也不是圆形球体

Scene Kit 的枢轴矩阵的语义是啥?

如何将复杂的 .dae 模型导入到 SceneKit?