2012-08-27 163 views
2

我试图创建一个测试应用程序,用户可以通过点击SceneView来暂停动画。 SceneView从3D应用程序(Cinema 4D)中创建的.dae文件加载动画。该应用成功播放并在发布后循环播放动画。暂停SceneKit动画

要暂停动画,我用Technical Q&A QA1673作为参考。在这个.dae文件的情况下,动画实际上是以动画的层次结构形式出现的,所以我试图深入到每个底层CAKeyframeAnimation并将其速度设置为零。我的代码目前看起来是这样的:

- (void)mouseDown:(NSEvent *)event { 

    SCNNode *cubeNode = [self.scene.rootNode childNodeWithName:@"C4D_Cube" recursively:YES]; 
    CAAnimation *cubeAnimation = [cubeNode animationForKey:@"Cube_Anim_01-02-1"];  
    CAAnimationGroup *cubeAnimationGroup = (CAAnimationGroup *)cubeAnimation; 

    // cubeAnimationGroup contains 3 CAAnimationGroups, each of which contains a CAKeyframeAnimation. 
    // So I directly access each CAKeyframeAnimation and set its speed to zero. 
    for (CAAnimationGroup *subGroup in [cubeAnimationGroup animations]) { 
      CFTimeInterval pausedTime = CACurrentMediaTime(); 
      [[subGroup animations] setValue:@0.0 forKey:@"speed"]; 
      [[subGroup animations] setValue:[NSNumber numberWithFloat:pausedTime] forKey:@"timeOffset"]; 
    } 
} 

当我设置一个断点,我可以看到,关键帧动画的速度也从1更改为0,但动画继续以正常速度在现场玩视图。我最初尝试将顶级CAAnimationGroup的速度设置为零,但这也没有效果。什么是暂停正在进行的动画的正确方法?

+0

更新死链接:[技术Q&A QA1673(https://developer.apple.com/library/content/qa/qa1673/_index.html) – edenwaith

回答

6

“animationForKey:”返回的动画是运行动画的副本。 该文档显示“尝试修改返回对象的任何属性将导致未定义的行为。” 所以你可以做这样的事情,而不是:

for(NSString *key in [myNode animationKeys]){ 
    CAAnimation *animation = [myNode animationForKey:key]; 
    [animation setSpeed:0]; //freeze 
    [animation setTimeOffset:CACurrentMediaTime() - [animation beginTime]]; //move back in time 
    [cube addAnimation:animation forKey:key]; //re-add the animation with the same key to replace 
} 

请注意,如果你只是想暂停从.DAE来的所有动画,你可能想要做的:

[mySCNView setPlaying:NO]; //暂停基于场景的动画

+0

谢谢!这非常有帮助。我忽略了SCNView上的setPlaying方法。当我尝试上面的代码示例时,我可以暂停动画,但只能在动画跳转到其时间轴上的其他位置后才能动画。我想知道时间偏移量是不是正确计算?理想情况下,我希望能够控制此方法提供的特定动画参数。 –

2

或者您可以将paused设置为true

在斯威夫特:

mySCNView.scene?.paused = true