在 Swift SceneKit 中使用 CAKeyframeAnimation 为 SCN 对象设置动画
Animating SCN Objects with CAKeyframeAnimation in Swift SceneKit
我正在编写一个以 3D 形式显示化学反应和分子的应用程序。我从文本文件中读取每个原子的所有值和位置,并使用 SCNSpheres 创建每个原子形状。我有我需要正确读入的所有其他值,但我不知道如何向场景中的每个节点对象添加关键帧动画。
我在 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)
}
我知道 CAKeyframeAnimations 应该这样设置
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")
我只是不知道我应该在哪里声明这些动画以及层如何影响这一切。我应该将动画添加到哪一层?我怎样才能触发他们玩?我一直在整个互联网上搜索这方面的帮助,但我找不到任何仅显示简单实现的内容。
如果需要,我可以提供更多代码,我是 Whosebug 的新手,想确保我做的是正确的。
你可以用不同的方式来做,但我喜欢这种方法:你可以pre-build一些使用 scenekit 的动画,然后 运行 它们作为一个序列。
根据评论..需要更多空间。
序列是固定的东西。您可以开始、重复和停止它。但是,在阶段中很难与之交互。
如果您确实需要这样做,那么一种方法是将您的序列分解成多个部分,并在当前序列的完成处理程序之后自行调用下一个序列。我保留了一个数组和一个计数器,这样我就知道我在哪里。所以基本上它只是我管理的一个动作队列 - 如果我在某个步骤并且按下了按钮,那么我可以取消所有当前动作,设置所需的效果,然后重新启动它。
编辑:
完成处理程序在函数末尾调用自身并增加自己的数组计数,以便可以调用列表中的下一个。这显然有点危险,所以我会谨慎使用,但我就是这样做的。我用定时器启动了我的,然后别忘了清理它。我有一个全局 GAME_ACTIVE 开关,我在代码中检查了它,然后再次调用自己。
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()
}
})
}
我正在编写一个以 3D 形式显示化学反应和分子的应用程序。我从文本文件中读取每个原子的所有值和位置,并使用 SCNSpheres 创建每个原子形状。我有我需要正确读入的所有其他值,但我不知道如何向场景中的每个节点对象添加关键帧动画。
我在 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)
}
我知道 CAKeyframeAnimations 应该这样设置
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")
我只是不知道我应该在哪里声明这些动画以及层如何影响这一切。我应该将动画添加到哪一层?我怎样才能触发他们玩?我一直在整个互联网上搜索这方面的帮助,但我找不到任何仅显示简单实现的内容。
如果需要,我可以提供更多代码,我是 Whosebug 的新手,想确保我做的是正确的。
你可以用不同的方式来做,但我喜欢这种方法:
根据评论..需要更多空间。
序列是固定的东西。您可以开始、重复和停止它。但是,在阶段中很难与之交互。
如果您确实需要这样做,那么一种方法是将您的序列分解成多个部分,并在当前序列的完成处理程序之后自行调用下一个序列。我保留了一个数组和一个计数器,这样我就知道我在哪里。所以基本上它只是我管理的一个动作队列 - 如果我在某个步骤并且按下了按钮,那么我可以取消所有当前动作,设置所需的效果,然后重新启动它。
编辑:
完成处理程序在函数末尾调用自身并增加自己的数组计数,以便可以调用列表中的下一个。这显然有点危险,所以我会谨慎使用,但我就是这样做的。我用定时器启动了我的,然后别忘了清理它。我有一个全局 GAME_ACTIVE 开关,我在代码中检查了它,然后再次调用自己。
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()
}
})
}