In SceneKit SCNAction hangs when called from completion handler of RunAction

纵然是瞬间 提交于 2019-12-13 04:27:38

问题


Calling an SCNAction from the completion handler of RunAction seems to hang SceneKit.

A touch event or rotating the device seems to unblock the hang.

To reproduce:

1) Take the default SceneKit project you get on startup with the rotating spaceship.

2) Replace the animation code:

ship.RunAction(SCNAction.RepeatActionForever(SCNAction.RotateBy(0, 2, 0, 1)));

with:

        ship.RunAction(SCNAction.RotateBy(0, 2, 0, durationInSeconds: 3.0f), delegate
        {
            Console.WriteLine("DONE ROTATE");
            ship.RunAction(SCNAction.MoveBy(1, 0, 0, durationInSeconds: 3.0f), delegate
            {
                Console.WriteLine("DONE MOVEBY");
            });
        });

3) Run on the simulator or real device (the problem is the same on both)

4) The results is:

  • Spaceship rotates OK

  • DONE ROTATE is printed out OK

  • Now it's hung

  • Tap the screen (or rotate the device to landscape) and then the move happens OK and DONE MOVEBY is printed out.

I'm using C# and Visual Studio for Mac, but I suspect it happens using Xcode too.

Is this a bug in SceneKit? How can a workaround be done?

Maybe this is the same issue as described here:

SCNAction completion handler awaits gesture to execute


回答1:


This happens because by default SceneKit is not rendering continuously. When tapping the screen the scene is changed and a new frame will be rendered. That's why the moveBy action is not triggered immediately after the rotateBy action.

Try setting SCNView's renderContinuously property to true like so:

scnView.rendersContinuously = true
ship.runAction(SCNAction.rotateBy(x: 0, y: 2, z: 0, duration: 3.0)) {
    print("DONE ROTATE")
    ship.runAction(SCNAction.moveBy(x: 1, y: 0, z: 0, duration: 3.0), completionHandler: {
        print("DONE MOVEBY")
        scnView.rendersContinuously = false
    })
}



回答2:


Using SCNTransaction with a completionBlock does not suffer from the same problem, so this works fine:

        SCNTransaction.Begin();
        SCNTransaction.AnimationDuration = 3.0f;
        SCNTransaction.SetCompletionBlock(() =>
        {
            Console.WriteLine("DONE ROTATE");
            SCNTransaction.Begin();
            SCNTransaction.AnimationDuration = 3.0f;
            SCNTransaction.SetCompletionBlock(() =>
            {
                Console.WriteLine("DONE MOVEBY");
            });
            ship.Position = new SCNVector3(1.0f, 0.0f, 0.0f);
            SCNTransaction.Commit();
        });
        ship.EulerAngles = new SCNVector3(0.0f, (float)Math.PI / 2, 0.0f);
        SCNTransaction.Commit();

(Also using CABasicAnimation with CAAnimationDelegate to do the callback works OK.)

Since SCNTransaction and CABasicAnimation work, but RunAction doesn't, it really looks like an Apple bug in RunAction.



来源:https://stackoverflow.com/questions/56189836/in-scenekit-scnaction-hangs-when-called-from-completion-handler-of-runaction

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!