SceneKit 在动画开始时闪烁
SceneKit flashes at start of animation
我在使用 SceneKit 动画时有一个不明白的行为。
以下所有代码都在 renderer:updateAtTime: 委托调用的上下文中执行。
我是这样制作动画的:
SCNVector4 startRotation = node.rotation ;
SCNVector4 targetRotation = pose.rotation ;
CABasicAnimation *rotAnimation = [CABasicAnimation animationWithKeyPath:@"rotation"] ;
rotAnimation.fromValue = [NSValue valueWithSCNVector4:startRotation] ;
rotAnimation.toValue = [NSValue valueWithSCNVector4:targetRotation] ;
rotAnimation.duration = duration ;
现在,如果我在 :
之后立即执行此操作
// First change the final rotation state, and then start the animation
node.rotation = targetRotation ;
[node addAnimation:rotAnimation forKey:animationName] ;
我在最终位置快速闪现角色,然后动画从 startRotation 运行到 targetRotation 并永远保持在 targetRotation 位置 - 这就是我想要的,除了闪现。
如果我改为这样做(只需交换最后两行的顺序):
// First start the animation and then set the final position
[node addAnimation:rotAnimation forKey:animationName] ;
node.rotation = targetRotation ;
我没有闪光灯,但是当动画结束时,角色回到初始位置,这不是我想要的。
我阅读了有关 fillMode 和 removedOnCompletion 的内容,但是将 removedOnCompletion 设置为 NO 是不正确的做法,因为它会永远保留动画 "running"。
如何避免初始闪光?
您似乎设置了两次节点的旋转:一次是通过动画,一次是通过直接操作。他们互相干扰。
尝试完全删除 node.rotation = targetRotation
。
故事是这样的。正如 Apple 在其文档中所述,SceneKit 渲染发生在循环中,并按以下顺序调用几个委托方法:
1 - renderer:updateAtTime:
(SceneKit 运行s 动画)
2 - renderer:didApply:AnimationsAtTime:
(...)
4 - renderer:willRenderSCne:atTime:
(SceneKit 渲染场景)
5 - renderer:didRenderScene:atTime:
现在,addAnimation:forKey 的文档:还说:"Newly added animations begin executing after the current run loop cycle ends"。
我跟踪了我的节点及其表示节点的旋转值。当我在renderer:updateAtTime中添加动画时:(第1步),我先设置节点目标位置,然后添加一个动画,但是这个动画不会在当前运行循环结束之前执行。所以 SceneKit 渲染这个最终位置(在步骤 4 和 5 之间),然后在下一个周期,SceneKit 将 运行 动画(在步骤 1 和 2 之间)并且 presentationNode 获得正确的值并在步骤之间再次渲染4 和 5 - 因此闪光灯。
相反,如果我在renderer:didRenderScene:atTime中添加动画:(第5步),循环结束,动画被安排在SceneKit之前运行s(第1步和第2步之间)达到渲染时间(在步骤 4 和 5 之间)。没有闪光灯。
我在使用 SceneKit 动画时有一个不明白的行为。 以下所有代码都在 renderer:updateAtTime: 委托调用的上下文中执行。
我是这样制作动画的:
SCNVector4 startRotation = node.rotation ;
SCNVector4 targetRotation = pose.rotation ;
CABasicAnimation *rotAnimation = [CABasicAnimation animationWithKeyPath:@"rotation"] ;
rotAnimation.fromValue = [NSValue valueWithSCNVector4:startRotation] ;
rotAnimation.toValue = [NSValue valueWithSCNVector4:targetRotation] ;
rotAnimation.duration = duration ;
现在,如果我在 :
之后立即执行此操作 // First change the final rotation state, and then start the animation
node.rotation = targetRotation ;
[node addAnimation:rotAnimation forKey:animationName] ;
我在最终位置快速闪现角色,然后动画从 startRotation 运行到 targetRotation 并永远保持在 targetRotation 位置 - 这就是我想要的,除了闪现。
如果我改为这样做(只需交换最后两行的顺序):
// First start the animation and then set the final position
[node addAnimation:rotAnimation forKey:animationName] ;
node.rotation = targetRotation ;
我没有闪光灯,但是当动画结束时,角色回到初始位置,这不是我想要的。
我阅读了有关 fillMode 和 removedOnCompletion 的内容,但是将 removedOnCompletion 设置为 NO 是不正确的做法,因为它会永远保留动画 "running"。
如何避免初始闪光?
您似乎设置了两次节点的旋转:一次是通过动画,一次是通过直接操作。他们互相干扰。
尝试完全删除 node.rotation = targetRotation
。
故事是这样的。正如 Apple 在其文档中所述,SceneKit 渲染发生在循环中,并按以下顺序调用几个委托方法:
1 - renderer:updateAtTime:
(SceneKit 运行s 动画)
2 - renderer:didApply:AnimationsAtTime:
(...)
4 - renderer:willRenderSCne:atTime:
(SceneKit 渲染场景)
5 - renderer:didRenderScene:atTime:
现在,addAnimation:forKey 的文档:还说:"Newly added animations begin executing after the current run loop cycle ends"。
我跟踪了我的节点及其表示节点的旋转值。当我在renderer:updateAtTime中添加动画时:(第1步),我先设置节点目标位置,然后添加一个动画,但是这个动画不会在当前运行循环结束之前执行。所以 SceneKit 渲染这个最终位置(在步骤 4 和 5 之间),然后在下一个周期,SceneKit 将 运行 动画(在步骤 1 和 2 之间)并且 presentationNode 获得正确的值并在步骤之间再次渲染4 和 5 - 因此闪光灯。
相反,如果我在renderer:didRenderScene:atTime中添加动画:(第5步),循环结束,动画被安排在SceneKit之前运行s(第1步和第2步之间)达到渲染时间(在步骤 4 和 5 之间)。没有闪光灯。