使用 CAKeyframeAnimation 在 Scenekit 中为旋转节点设置动画

Posted

技术标签:

【中文标题】使用 CAKeyframeAnimation 在 Scenekit 中为旋转节点设置动画【英文标题】:Animate rotation node in Scenekit using CAKeyframeAnimation 【发布时间】:2021-12-21 19:06:22 【问题描述】:

为了学习 ARKit 和 SceneKit,我正在编写一个简单的应用程序,它应该做两件事:

    在 3D 世界中放置一架飞机

    为这架飞机制作动画,以使这架飞机以圆形方式飞行(如果我能让这架飞机在方形路径上飞行,我会很高兴)。

现在,我被困在第二点,为飞机设置动画。

我尝试了不同的方法,但没有成功。

第一次尝试:使用“sequanceAction”进行动画处理,但您可以从以下代码中看到,平面首先移动到旋转的 X(Yaxes),然后移动到 Z(动画非常难看)。

func animataAirplane(nodeToAnimate: SCNNode)
    let moveinx = SCNAction.move(to: SCNVector3(nodeToAnimate.position.x + 1,nodeToAnimate.position.y,nodeToAnimate.position.z), duration: 2)
    let rotateRight = SCNAction.rotate(by: deg2rad(-90), around: SCNVector3(0, 1, 0), duration: 1)
    let moveinz = SCNAction.move(to: SCNVector3(nodeToAnimate.position.x + 1,nodeToAnimate.position.y,nodeToAnimate.position.z + 1), duration: 2)
    let sequanceAction = SCNAction.sequence([moveinx, rotateRight, moveinz])
    nodeToAnimate.runAction(sequenceAction)

我想要的是过度的动画,几乎在 moveX 动作结束时开始旋转动作和 moveinZ,以便给出真正平面转弯的错觉。

这可能吗?我正在寻找有人指出我应该看的正确方向。

我的第二种方法是尝试“CAKeyframeAnimation”:

但我无法准确找到如何组合此动画:

func animatePlaneKey(nodeToAnimate: SCNNode)
    let pos = nodeToAnimate.position
    let animation = CAKeyframeAnimation(keyPath: "position")
    let pos1 = SCNVector3(pos.x, pos.y, pos.z)
    let pos2 = SCNVector3(pos.x + 1 , pos.y, pos.z)
    let pos3 = SCNVector3(pos.x + 1 , pos.y, pos.z + 1)

    animation.values = [pos1,pos2, pos3]
    animation.keyTimes = [0,0.5,1]
    animation.calculationMode = .linear
    animation.duration = 10
    animation.repeatCount = 1
    animation.isAdditive = true
            
    let animation2 = CAKeyframeAnimation(keyPath: "rotation")
    let pos1rot = SCNVector3(nodeToAnimate.eulerAngles.x, nodeToAnimate.eulerAngles.y, nodeToAnimate.eulerAngles.z)
    let pos2rot = SCNVector3(nodeToAnimate.eulerAngles.x + Float(deg2rad(90)), nodeToAnimate.eulerAngles.y + Float(deg2rad(90)), nodeToAnimate.eulerAngles.z + Float(deg2rad(90)))
    animation2.values = [pos1rot,pos2rot]
    animation2.keyTimes = [0,1]
    animation2.duration = 2
    animation2.repeatCount = 1
    animation2.isAdditive = true
            
    nodeToAnimate.addAnimation(animation, forKey: "position")
    nodeToAnimate.addAnimation(animation2, forKey: "rotation")

如果有人能指出正确的方向来模拟这个飞行动画,我会很高兴。

非常感谢。

【问题讨论】:

您可以在节点上触发第二个动画。即前。第一个动画序列,将飞机从 A 移动到 B 到 C 到 D,然后回到 A - 第二个序列以您想要的方式旋转飞机。你可以在旋转动作之间添加一些暂停(SCNAction.wait)。这样它只有在靠近角落时才会旋转。然后将两个操作附加到您的节点。 【参考方案1】:

这是您的代码的工作版本:

func animatePlaneKey(nodeToAnimate: SCNNode) 

    let pos = nodeToAnimate.position
    let animation = CAKeyframeAnimation(keyPath: "position")
    let pos1 = SCNVector3(pos.x, pos.y, pos.z)
    let pos2 = SCNVector3(pos.x + 1 , pos.y, pos.z)
    let pos3 = SCNVector3(pos.x + 1 , pos.y, pos.z + 1)

    animation.values = [pos1,pos2, pos3]
    animation.keyTimes = [0,0.5,1]
    animation.calculationMode = .linear
    animation.duration = 10
    animation.repeatCount = 1
    animation.isAdditive = true
            
    let animation2 = CAKeyframeAnimation(keyPath: "rotation")
    let pos1rot = SCNVector4(0, 0, 0, 0)
    let pos2rot = SCNVector4(0, 1, 0, CGFloat(Float.pi/2))
    animation2.values = [pos1rot, pos2rot]
    animation2.keyTimes = [0, 1]
    animation2.duration = 20
    animation2.repeatCount = 1
    animation2.isAdditive = true
            
    nodeToAnimate.addAnimation(animation, forKey: "position")
    nodeToAnimate.addAnimation(animation2, forKey: "spin around")

【讨论】:

以上是关于使用 CAKeyframeAnimation 在 Scenekit 中为旋转节点设置动画的主要内容,如果未能解决你的问题,请参考以下文章

具有交错开始时间的 CAKeyframeAnimation

如何在 Iphone 中停止 CAKeyFrameAnimation

使用 CAKeyframeAnimation 在 Scenekit 中为旋转节点设置动画

中断和反转 CAKeyframeAnimation

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

如何使用 CAKeyFrameAnimation 继续旋转视图?