【问题标题】:SceneKit flashes at start of animationSceneKit 在动画开始时闪烁
【发布时间】:2017-10-21 07:31:18
【问题描述】:

我在使用 SceneKit 动画时遇到了我不理解的行为。 以下所有代码都在渲染器的上下文中执行: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 位置 - 这是我想要的,除了 flash。

如果我这样做(只需交换最后两行的顺序):

         // First start the animation and then set the final position
         [node addAnimation:rotAnimation forKey:animationName] ;
         node.rotation  = targetRotation ;

我没有闪光灯,但是当动画结束时,角色回到初始位置,这不是我想要的。

我阅读了有关fillMode 和removedOnCompletion 的信息,但是将removedOnCompletion 设置为NO 是不正确的做法,因为它会使动画永远“运行”。

如何避免初闪?

【问题讨论】:

  • 我认为您应该在 renderer:updateAtTime: 之外制作动画,因为文档说任何场景更改都会立即应用。 (所以我猜在添加动画之前节点会更新。)
  • 好吧,几乎...我认为当您说“在渲染器之外制作动画:updateAtTime:”时您是对的。但是,并不是因为更改会立即应用。我经历了漫长的调查,我想我现在明白发生了什么。简而言之,如果在 renderer:didRenderScene:atTime: 中执行,我的代码可以完美运行(没有 flash)。为了记录和帮助他人,我将写一个详细的解释并回答我自己的问题。

标签: macos animation scenekit


【解决方案1】:

您似乎设置了两次节点的旋转:一次使用动画,一次通过直接操作。他们互相干扰。

尝试完全删除node.rotation = targetRotation

【讨论】:

  • 是的,我这样做。但这是 Apple 推荐的动画制作方式 (developer.apple.com/library/content/documentation/Cocoa/…)。如果你不设置node.rotation,那么在动画结束时,你又回到了初始值。问题是在添加动画之前似乎需要这样做 - 这是一个未记录的点 - 但这会使动画闪烁。
【解决方案2】:

故事就是这样。正如 Apple 在其文档中所述,SceneKit 渲染发生在一个循环中,并且按以下顺序调用了几个委托方法:

1 - 渲染器:updateAtTime:

(SceneKit 运行动画)

2 - 渲染器:didApply:AnimationsAtTime:

(...)

4 - 渲染器:willRenderSCne:atTime:

SceneKit 渲染场景

5 - 渲染器:didRenderScene:atTime:

现在,addAnimation:forKey: 的文档还说:“新添加的动画开始执行在当前运行循环周期结束后”。

我跟踪了我的节点及其表示节点的旋转值。当我在 renderer:updateAtTime: 中添加动画时(第 1 步),我首先设置了节点目标位置,然后添加了动画,但是在当前运行循环结束之前不会执行此动画。所以 SceneKit 渲染这个最终位置(在第 4 步和第 5 步之间),然后,在下一个循环中,SceneKit 将运行动画(在第 1 步和第 2 步之间),presentationNode 获得正确的值并在第 4 步和第 5 步之间再次渲染 -因此闪光。

相反,如果我在 renderer:didRenderScene:atTime: (步骤 5)中添加动画,则循环结束,动画在 SceneKit 到达渲染时间(步骤之间4 和 5)。没有闪光灯。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-12
    • 1970-01-01
    • 2019-04-06
    • 1970-01-01
    • 2011-12-02
    • 2012-03-12
    • 2011-03-30
    • 2011-08-23
    相关资源
    最近更新 更多