在Swift SceneKit中使用CAKeyframeAnimation设置SCN对象的动画

在Swift SceneKit中使用CAKeyframeAnimation设置SCN对象的动画,swift,animation,scenekit,keyframe,Swift,Animation,Scenekit,Keyframe,我正在写一个3D显示化学反应和分子的应用程序。我从一个文本文件中读取每个原子的所有值和位置,并使用scnsphere创建每个原子形状。我有需要正确读取的所有其他值,但我不知道如何向场景中的每个节点对象添加关键帧动画 我在ViewController.swift中设置了这样的分子 func makeAtom(atomName: String, coords: [Double], scene: SCNScene) { guard let radius = atomRadii[atom

我正在写一个3D显示化学反应和分子的应用程序。我从一个文本文件中读取每个原子的所有值和位置,并使用scnsphere创建每个原子形状。我有需要正确读取的所有其他值,但我不知道如何向场景中的每个节点对象添加关键帧动画

我在ViewController.swift中设置了这样的分子

func makeAtom(atomName: String, coords: [Double], scene: SCNScene) {
        guard let radius = atomRadii[atomName]?.atomicRadius else { return }
        
        atoms.append(Atom(name: atomName, x: coords[0], y: coords[1], z: coords[2], radius: radius, positions: []))
        
        let atomGeometry = SCNSphere(radius: CGFloat(radius))
        let atomNode = SCNNode(geometry: atomGeometry)
        atomNode.position = SCNVector3(coords[0], coords[1], coords[2])
        scene.rootNode.addChildNode(atomNode)
        
        atomNodes.append(atomNode)
    }
我知道CakeyImation应该是这样设置的

let animation = CAKeyframeAnimation()
animation.keyPath = "position.y"
animation.values = [0, 300, 0]
animation.keyTimes = [0, 0.5, 1]
animation.duration = 2
animation.isAdditive = true

vw.layer.add(animation, forKey: "move")
我只是不知道我应该在哪里声明这些动画,以及层是如何融入所有这些的。我应该将动画添加到哪个层?我怎样才能让他们玩呢?我一直在互联网上寻找这方面的帮助,但我找不到任何只显示一个简单实现的东西


如果需要的话,我可以提供更多的代码,我对StackOverflow还很陌生,我想确保我做得正确。

你可以用不同的方法来做,但我喜欢这种方法:因为你可以使用scenekit预建一些动画,然后按顺序运行。

根据评论。。需要更多的空间

序列是固定的。你可以开始、重复和停止它。然而,在各个阶段很难与之互动

如果您确实需要这样做,那么一种方法是将序列分解为各个部分,并在当前序列的完成处理程序之后自己调用下一个序列。我保留了一个数组和一个计数器,以便知道我在哪里。因此,基本上,我只需要管理一个操作队列——如果我在某个步骤上,按下按钮,那么我可以取消所有当前操作,设置所需的效果,然后重新启动它

编辑:

完成处理程序在函数末尾调用自己,并推进自己的数组计数,以便可以调用列表中的下一个数组。这显然有点危险,所以我会谨慎使用,但我就是这样做的。我是用定时器启动的,别忘了清理。我有一个全局GAME_活动开关,在再次调用自己之前,我在代码中检查了它

Edit2:这实际上是一个moveTo,但它仍然只是一组自定义的scnaction,在完成时根据持续时间调用自己,以便立即转到下一个,而不会延迟

func moveTo()
    {
        let vPanelName = moves[moveCount]
        let vLaneNode = grid.gridPanels[vPanelName]!.laneNodes[lane]
        let vAction = SCNAction.move(to: vLaneNode.presentation.position, duration: TimeInterval(data.getAttackSpeed(vGameType: gameType)))
        
        node.runAction(vAction, completionHandler:
            {
                self.moveCount += 1
                if(self.moveCount >= self.moves.count - 1)
                {
                    self.killMe(vRealKill: false)
                    return
                }
                else
                {
                    self.moveTo()
                }
        })
    }

这非常有效,我现在唯一的问题是,是否有方法访问当前正在运行的操作?例如,如果我按下屏幕上的一个按钮,在那一刻我可以访问当前正在执行的操作吗?你介意分享一下你是如何做到的吗?我有我想要执行的scnaction数组(不是序列),我得到了完成处理程序,但我不知道如何编码它,以便它继续调用下一个。我猜它必须在一个循环中,但我不确定它会是什么样子。很抱歉,继续回到这里,但是完成处理程序中的动画代码正在访问,但它实际上不会执行动画。我遗漏了什么明显的东西吗?你能分享一下你使用的代码吗?这不是一件小事——依我看,这相当棘手,但这是我所知道的唯一一种方法,可以让你真正以你所描述的方式与动作互动。真的,你在那里做的是一次一个地调用每个动作,并通过计时器调节更改。我认为我做得正确,因为它可以工作一点,但问题是atom动画有数百到数千个步骤,我认为应用程序在一段时间后会耗尽内存,整个事情都冻结了。这似乎是对的,还是我可能做了其他错误的事情?