同时在多个SceneKit节点上进行CAAnimation

时间:2017-12-05 13:05:02

标签: ios swift scenekit arkit caanimation

我正在创建一个应用程序,其中我在AR应用程序中使用SceneKit内容。我有多个节点放在我的场景中的不同位置。它们可能或可能不一定在一个父节点内。用户必须根据应用程序设置的挑战选择正确的节点。如果用户选择了正确的节点,则正确的节点将经历一种动画,而不正确的节点(可能是几种)经历另一组动画。我正在使用CAAnimation直接完成动画,这一切都很好。基本上要实现这一点,我正在创建一个包含所有节点的数组并将它们用于动画。

DispatchQueue.global(qos: .userInteractive).async { [weak self] in
    for node in (self?.nodesAddedInScene.keys)! {
        for index in 1...node.childNodes.count - 1 {
            if node.childNodes[index].childNodes.first?.name == "target" {
                self?.riseUpSpinAndFadeAnimation(on: node.childNodes[index])
            } else {
                self?.fadeAnimation(on: node.childNodes[index])
            }
        }
    }
}

当用户选择“目标”节点时,该节点将经历一组动画,而其他节点则通过另一组动画。

RiseUpSpinAndFadeAnimation:

    private func riseUpSpinAndFadeAnimation(on shape: SCNNode) {
        let riseUpAnimation = CABasicAnimation(keyPath: "position")
        riseUpAnimation.fromValue = SCNVector3(shape.position.x, shape.position.y, shape.position.z)
        riseUpAnimation.toValue = SCNVector3(shape.position.x, shape.position.y + 0.5, shape.position.z)

        let spinAnimation = CABasicAnimation(keyPath: "eulerAngles.y")
        spinAnimation.toValue = shape.eulerAngles.y + 180.0
        spinAnimation.autoreverses = true

        let fadeAnimation = CABasicAnimation(keyPath: "opacity")
        fadeAnimation.toValue = 0.0

        let riseUpSpinAndFadeAnimation = CAAnimationGroup()
        riseUpSpinAndFadeAnimation.animations = [riseUpAnimation, fadeAnimation, spinAnimation]
        riseUpSpinAndFadeAnimation.duration = 1.0
        riseUpSpinAndFadeAnimation.fillMode = kCAFillModeForwards
        riseUpSpinAndFadeAnimation.isRemovedOnCompletion = false

        shape.addAnimation(riseUpSpinAndFadeAnimation, forKey: "riseUpSpinAndFade")
    }

FadeAnimation:

private func fadeAnimation(on shape: SCNNode) {
    let fadeAnimation = CABasicAnimation(keyPath: "opacity")
    fadeAnimation.toValue = 0.0
    fadeAnimation.duration = 0.5
    fadeAnimation.fillMode = kCAFillModeForwards
    fadeAnimation.isRemovedOnCompletion = false
    shape.addAnimation(fadeAnimation, forKey: "fade")
}

我希望动画可以实现,实际上是动画。但是,问题是由于节点处于数组动画中,因此并非所有节点都同时完成。动画的开始存在微小的差异,实际上导致不那么好的UI。

我正在寻找的是一种逻辑,我可以在所有节点上附加动画,并稍后将这些动画称为一起当我们说用户点击正确的节点时。数组对我来说似乎不是一个明智的选择。但是,我担心如果我将所有这些节点都作为空节点的子节点和该空节点上的运行动画,可能首先要管理这些子节点的位置是很困难的,因为它们应该保留在随机距离并不一定靠近。鉴于这最终会推动AR体验,因此它变得更加糟糕。

请求一些输入是否有方法将动画附加到多个(从中选择)对象(即使顺序),但将它们一起运行。我使用shape.addAnimation(fadeAnimation, forKey: "fade")“forKey”,可以在这种用例中使用吗?任何指针赞赏。

2 个答案:

答案 0 :(得分:2)

通过使用暂停(.speed = 0)的CAKeyframe动画并在SCNSceneRendererDelegate内设置动画的时间偏移(.timeOffset),我有多达50个SCNNodes完美和谐地制作动画效果&#34 ;渲染器(updateAtTime:)"功能

如何为大量节点添加每1/60秒的时间偏移量的暂停动画,这真是太神奇了。向SceneKit开发人员致敬,因为他们在添加和删除CAAnimations方面的开销很小。

在解决这个问题之前,我尝试了许多不同的CAAnimation / SCNAction技术。在其他方法中,动画会随着时间的推移而不同步。

答案 1 :(得分:1)

锰,

我只是在这里猜测或者可以为你提出一个想法: - )

我关注的是你问题的这一部分: "我正在寻找的是一种逻辑,我可以在所有节点上附加动画,并在以后让用户点击正确的节点时将这些动画调用在一起。"

我想知道SCNTransaction: [https://developer.apple.com/documentation/scenekit/scntransaction][1] 可能会做的伎俩

或者也许是dispatch.sync或async(完全猜测......但可以提供帮助) [https://developer.apple.com/documentation/dispatch][1]

或者我离开了标记:-) 只是想帮忙......

我们都通过分享我们所知道的东西来学习

RAD