简体   繁体   English

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

[英]CAAnimation on multiple SceneKit nodes simultaneously

I am creating an application wherein I am using SceneKit contents in AR app. 我正在创建一个应用程序,其中我在AR应用程序中使用SceneKit内容。 I have multiple nodes which are being placed at different places in my scene. 我有多个节点放在我的场景中的不同位置。 They may or may not be necessarily be inside one parent node. 它们可能或可能不一定在一个父节点内。 The user has to choose a correct node, as per challenge set by the application. 用户必须根据应用程序设置的挑战选择正确的节点。 If the user chooses correct node, the correct node goes through one kind of animation and incorrect ones (may be several) undergo another set of animation. 如果用户选择了正确的节点,则正确的节点将经历一种动画,而不正确的节点(可能是几种)经历另一组动画。 I am accomplishing animations using CAAnimation directly, which is all good. 我正在使用CAAnimation直接完成动画,这一切都很好。 Basically to accomplish this, I am creating an array of all nodes and using them for animation. 基本上要实现这一点,我正在创建一个包含所有节点的数组并将它们用于动画。

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

When user chooses "target" node, that node goes through one set of animation and others go through another set of animations. 当用户选择“目标”节点时,该节点将经历一组动画,而其他节点则通过另一组动画。

RiseUpSpinAndFadeAnimation: 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: 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")
}

I expect animations to work out, which they are actually. 我希望动画可以实现,实际上它们也是如此。 However, the issue is since the nodes are in an array animation is not being done at the same time for all nodes. 但是,问题是由于节点处于数组动画中,因此并非所有节点都同时完成。 There are minute differences in start of animation which actually is leading to not so good UI. 动画的开始存在微小的差异,实际上导致不那么好的UI。

What I am looking for is a logic wherein I can attach animations on all nodes and call these animations together later when let's say the user taps correct node. 我正在寻找的是一种逻辑,其中我可以在所有节点上附加动画,并且稍后当我们说用户点击正确的节点时将这些动画调用在一起 Arrays don't seem to be a wise choice to me. 数组对我来说似乎不是一个明智的选择。 However, I am afraid if I make all of these nodes child nodes of an empty node and the run animation on that empty node, possibly it would be difficult to manage placement of these child nodes in the first place since they supposed to be kept at random distances and not necessarily close together. 但是,我担心如果我将所有这些节点都作为空节点的子节点和该空节点上的运行动画,可能首先要管理这些子节点的位置是很困难的,因为它们应该保留在随机距离并不一定靠近。 Given that this ultimately drives AR experience, it more so becomes a bummer. 鉴于这最终会推动AR体验,因此它变得更加糟糕。

Requesting some inputs whether there are methods to attach animation to multiple (selected out of those) object (even if sequentially) but RUN them together. 请求一些输入是否有方法将动画附加到多个(从中选择)对象(即使顺序)但将它们一起运行。 I used shape.addAnimation(fadeAnimation, forKey: "fade") "forKey", can that be made of use in such use case? 我使用shape.addAnimation(fadeAnimation, forKey: "fade") “forKey”,可以在这种用例中使用吗? Any pointers appreciated. 任何指针赞赏。

I've had up to fifty SCNNodes animating in perfect harmony by using CAKeyframe animations that are paused (.speed = 0) and setting the animation's time offset (.timeOffset) inside a SCNSceneRendererDelegate "renderer(updateAtTime:)" function. 通过使用暂停(.speed = 0)的CAKeyframe动画并在SCNSceneRendererDelegate“renderer(updateAtTime :)”函数内设置动画的时间偏移(.timeOffset),我已经有多达50个SCNNodes动画完美和谐。

It's pretty amazing how you can add a paused animation with an time offset every 1/60th of a second for a large number of nodes. 令人惊讶的是,如何为大量节点添加每1/60秒的时间偏移的暂停动画。 Hats off to the SceneKit developers for having so little overhead on adding and removing CAAnimations. 向SceneKit开发人员致敬,因为他们在添加和删除CAAnimations方面的开销很小。

I tried many different CAAnimation/SCNAction techniques before settling on this. 在解决这个问题之前,我尝试了许多不同的CAAnimation / SCNAction技术。 In other methods the animations would drift out of sync over time. 在其他方法中,动画会随着时间的推移而不同步。

Manganese, 锰,

I am just taking a guess here or could spark an idea for you :-) 我只是在这里猜测或者可以为你激发一个想法:-)

I am focusing on this part of your question: "What I am looking for is a logic wherein I can attach animations on all nodes and call these animations together later when let's say the user taps correct node." 我正在关注你问题的这一部分:“我正在寻找的是一种逻辑,我可以在所有节点上附加动画,并在以后让用户点击正确的节点时将这些动画调用在一起。”

I wonder if SCNTransaction: [ https://developer.apple.com/documentation/scenekit/scntransaction][1] might do the trick 我想知道SCNTransaction:[ https://developer.apple.com/documentation/scenekit/scntransaction] [1 ]是否可以做到这一点

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

or I am way off the mark :-) just trying to help out.... 或者我离开了标记:-)只是想帮忙....

We all learn by sharing what we know 我们通过分享我们所知道的东西来学习

RAD RAD

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM