将 timingFunction 添加到 SCNAction 会中断动作完成处理程序
Adding timingFunction to SCNAction breaks action completion handler
我有一个奇怪的情况。我正在尝试 运行 动画,我正在等待完成处理程序。在我定义 timingFunction 之前一切正常。在那之后,有时根本不会调用 completionHandler。我的动画卡在最后一帧。
CGFloat rotations = times * 2.0;
CGFloat zoomLevel = COIN_MOVE_UP;
SCNAction* rotate = [SCNAction rotateByX:M_PI_2 y:0 z:0 duration:2.0 / (rotations + 1)];
NSUInteger swaps = rotations / 2;
SCNAction* rotateSequence = [SCNAction repeatAction:rotate count:2];
SCNAction* coinRotate = [SCNAction repeatAction:rotateSequence count:swaps];
SCNAction* coinRotateAction = [SCNAction sequence:@[coinRotate, rotate]];
SCNAction* coinMoveUpAction = [SCNAction moveByX:0 y:-zoomLevel z:0 duration:1];
SCNAction* coinMoveDownAction = [SCNAction moveByX:0 y:zoomLevel z:0 duration:1];
SCNAction* coinMoveAction = [SCNAction sequence:@[coinMoveUpAction, coinMoveDownAction]];
SCNAction* coinRotateY = [SCNAction rotateByX:0 y:M_PI z:0 duration:2];
SCNAction* fullGroup = [SCNAction group:@[coinRotateAction, coinMoveAction, coinRotateY]];
[fullGroup setTimingFunction:^(float time){
return time;
}];
[self.coinNode runAction:fullGroup completionHandler:^{
// completion is not called sometimes when timingFunction is efined
}];
你知道如何解决这个问题吗?
P.S。
我实施了:
-(void)renderer:(id<SCNSceneRenderer>)renderer didApplyAnimationsAtTime:(NSTimeInterval)time{
}
如果没有计时功能,此方法会在动画完成时停止调用,但当存在 timig 功能时,有时动画 运行 会一直持续到结束,但不会调用完成处理程序,并且仍在调用 didApplyAnimationsAtTime:。所以也许这个动画在达到结束状态后仍然 运行ning。
我终于能够使用
解决这个问题
+ (SCNAction *)customActionWithDuration:(NSTimeInterval)seconds actionBlock:(void (^)(SCNNode *node, CGFloat elapsedTime))block;
所以我删除了所有计时函数并将它们重新实现为块:
CGFloat angle = M_PI_2;
void (^block)(SCNNode * _Nonnull node, CGFloat elapsedTime) = ^(SCNNode * _Nonnull node, CGFloat elapsedTime) {
CGFloat progress = elapsedTime / duration;
CGFloat realTime = pow(progress, 6); // here I apply timing
node.eulerAngles = SCNVector3Make(initialVector.x + (angle * realTime), initialVector.y, initialVector.z);
node.position = SCNVector3Make(node.position.x, cos(angle * realTime) * 5, sin(angle * realTime) * 5);
};
这样我就没有任何未调用的完成处理程序的问题,我仍然可以调整我的动画的时间:)
我有一个奇怪的情况。我正在尝试 运行 动画,我正在等待完成处理程序。在我定义 timingFunction 之前一切正常。在那之后,有时根本不会调用 completionHandler。我的动画卡在最后一帧。
CGFloat rotations = times * 2.0;
CGFloat zoomLevel = COIN_MOVE_UP;
SCNAction* rotate = [SCNAction rotateByX:M_PI_2 y:0 z:0 duration:2.0 / (rotations + 1)];
NSUInteger swaps = rotations / 2;
SCNAction* rotateSequence = [SCNAction repeatAction:rotate count:2];
SCNAction* coinRotate = [SCNAction repeatAction:rotateSequence count:swaps];
SCNAction* coinRotateAction = [SCNAction sequence:@[coinRotate, rotate]];
SCNAction* coinMoveUpAction = [SCNAction moveByX:0 y:-zoomLevel z:0 duration:1];
SCNAction* coinMoveDownAction = [SCNAction moveByX:0 y:zoomLevel z:0 duration:1];
SCNAction* coinMoveAction = [SCNAction sequence:@[coinMoveUpAction, coinMoveDownAction]];
SCNAction* coinRotateY = [SCNAction rotateByX:0 y:M_PI z:0 duration:2];
SCNAction* fullGroup = [SCNAction group:@[coinRotateAction, coinMoveAction, coinRotateY]];
[fullGroup setTimingFunction:^(float time){
return time;
}];
[self.coinNode runAction:fullGroup completionHandler:^{
// completion is not called sometimes when timingFunction is efined
}];
你知道如何解决这个问题吗?
P.S。 我实施了:
-(void)renderer:(id<SCNSceneRenderer>)renderer didApplyAnimationsAtTime:(NSTimeInterval)time{
}
如果没有计时功能,此方法会在动画完成时停止调用,但当存在 timig 功能时,有时动画 运行 会一直持续到结束,但不会调用完成处理程序,并且仍在调用 didApplyAnimationsAtTime:。所以也许这个动画在达到结束状态后仍然 运行ning。
我终于能够使用
解决这个问题+ (SCNAction *)customActionWithDuration:(NSTimeInterval)seconds actionBlock:(void (^)(SCNNode *node, CGFloat elapsedTime))block;
所以我删除了所有计时函数并将它们重新实现为块:
CGFloat angle = M_PI_2;
void (^block)(SCNNode * _Nonnull node, CGFloat elapsedTime) = ^(SCNNode * _Nonnull node, CGFloat elapsedTime) {
CGFloat progress = elapsedTime / duration;
CGFloat realTime = pow(progress, 6); // here I apply timing
node.eulerAngles = SCNVector3Make(initialVector.x + (angle * realTime), initialVector.y, initialVector.z);
node.position = SCNVector3Make(node.position.x, cos(angle * realTime) * 5, sin(angle * realTime) * 5);
};
这样我就没有任何未调用的完成处理程序的问题,我仍然可以调整我的动画的时间:)