同时在多个 SceneKit 节点上执行 CAAnimation
CAAnimation on multiple SceneKit nodes simultaneously
我正在创建一个应用程序,其中我在 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])
}
}
}
}
当用户选择 "target" 节点时,该节点执行一组动画,其他节点执行另一组动画。
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",在这种用例中可以使用吗?任何指针表示赞赏。
锰,
我只是在这里猜测一下,或者可以为您激发一个想法:-)
我主要关注你问题的这一部分:
"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."
我想知道 SCNTransaction 是否:
[https://developer.apple.com/documentation/scenekit/scntransaction][1]
可能会成功
或者 dispatch.sync 或异步(完全是猜测......但可能有所帮助)
[https://developer.apple.com/documentation/dispatch][1]
或者我离题太远了:-)
只是想帮忙....
我们都通过分享我们所知道的来学习
RAD
通过使用暂停的 CAKeyframe 动画 (.speed = 0) 并在 SCNSceneRendererDelegate "renderer(updateAtTime:)" 函数中设置动画的时间偏移 (.timeOffset),我有多达五十个 SCNNodes 完美和谐地制作动画。
如何为大量节点添加每 1/60 秒的时间偏移的暂停动画真是太神奇了。向 SceneKit 开发人员致敬,他们在添加和删除 CAAnimations 方面的开销如此之小。
我尝试了许多不同的 CAAnimation/SCNAction 技术,然后才决定使用它。在其他方法中,动画会随着时间的推移不同步。
我正在创建一个应用程序,其中我在 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])
}
}
}
}
当用户选择 "target" 节点时,该节点执行一组动画,其他节点执行另一组动画。
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",在这种用例中可以使用吗?任何指针表示赞赏。
锰,
我只是在这里猜测一下,或者可以为您激发一个想法:-)
我主要关注你问题的这一部分: "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."
我想知道 SCNTransaction 是否: [https://developer.apple.com/documentation/scenekit/scntransaction][1] 可能会成功
或者 dispatch.sync 或异步(完全是猜测......但可能有所帮助) [https://developer.apple.com/documentation/dispatch][1]
或者我离题太远了:-) 只是想帮忙....
我们都通过分享我们所知道的来学习
RAD
通过使用暂停的 CAKeyframe 动画 (.speed = 0) 并在 SCNSceneRendererDelegate "renderer(updateAtTime:)" 函数中设置动画的时间偏移 (.timeOffset),我有多达五十个 SCNNodes 完美和谐地制作动画。
如何为大量节点添加每 1/60 秒的时间偏移的暂停动画真是太神奇了。向 SceneKit 开发人员致敬,他们在添加和删除 CAAnimations 方面的开销如此之小。
我尝试了许多不同的 CAAnimation/SCNAction 技术,然后才决定使用它。在其他方法中,动画会随着时间的推移不同步。