【问题标题】:SpriteKit- the right way to multitaskSpriteKit-多任务的正确方法
【发布时间】:2023-03-09 13:42:01
【问题描述】:

我试图在代码中的任何地方搜索:解释文档在进入后台时会做什么,或者它是否有时会暂停,但无济于事 - 有人可以指导我按照推荐的方式去做到启用精灵套件的游戏中的背景?

我应该直接打电话给scene.paused = YES,或者我如何确认后台没有绘图,这样我就可以避免iOS 不允许我这样做?

谢谢!

【问题讨论】:

    标签: background ios7 sprite-kit


    【解决方案1】:

    正如here LearnCocos2D所说:

    问题是当应用进入后台时 AVAudioSession 无法激活。

    修复非常简单,也适用于 ObjectAL => 将 AVAudioSession 设置为在应用程序处于后台时处于非活动状态,并在应用程序进入前台时重新激活音频会话。

    经过此修复的简化 AppDelegate 如下所示:

    #import <AVFoundation/AVFoundation.h>
    
    ...
    
    - (void)applicationWillResignActive:(UIApplication *)application
    {
        // prevent audio crash
        [[AVAudioSession sharedInstance] setActive:NO error:nil];
    }
    
    - (void)applicationDidEnterBackground:(UIApplication *)application
    {
        // prevent audio crash
        [[AVAudioSession sharedInstance] setActive:NO error:nil];
    }
    
    - (void)applicationWillEnterForeground:(UIApplication *)application
    {
        // resume audio
        [[AVAudioSession sharedInstance] setActive:YES error:nil];
    }
    

    PS:此修复将包含在 Kobold Kit v7.0.3 中。

    【讨论】:

    • 第二个有必要吗?
    • 这修复了它。显然,SpriteKit 还不能很好地处理音频。
    • 此问题已在 iOS8 中修复。 iOS7 及更低版本崩溃。
    【解决方案2】:

    对我来说,没有一个提供解决方案。我确实找到了另一种方法。

    // In the AppDelegate
    - (void)applicationWillResignActive:(UIApplication *)application
    {
        if ([self.window.rootViewController isKindOfClass:[GameViewController class]]) {
            GameViewController *vc = (GameViewController*)self.window.rootViewController;
            [vc pauseGame];
            [vc.view addObserver:vc
                      forKeyPath:@"paused"
                         options:NSKeyValueObservingOptionNew
                         context:nil];
        }
    }
    
    // In the GameViewController
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
    {
        SKView *skView = (SKView*)self.view;
        MainGame *mainGame = (MainGame*)skView.scene;
        if ([keyPath isEqualToString:@"paused"] &&
            [[change objectForKey:NSKeyValueChangeNewKey] boolValue] == NO &&
            [mainGame isGameInProgress]) {
            [self.view removeObserver:self forKeyPath:@"paused" context:nil];
            skView.paused = YES;
        }
    }
    

    【讨论】:

      【解决方案3】:

      我想知道为什么这个看似简单的解决方案会导致我在应用程序启动时崩溃,但这是因为我运行了 iAd。 所以,要记住一件事:@MassivePenguin 的回答有效,但如果你有 iAd 运行,你将不得不通过 subviews 获取 SKView,否则它(显然)会崩溃。

      -(SKView*)getSKViewSubview{
          for (UIView* s in self.window.rootViewController.view.subviews) {
              if ([s isKindOfClass:[SKView class]]) {
                  return (SKView*)s;
              }
          }
          return nil;
      }
      
      - (void)applicationWillResignActive:(UIApplication *)application {    
          SKView* view = [self getSKViewSubview];
      
          if (view) {
              view.paused = YES;
          }
      
      }
      
      - (void)applicationDidBecomeActive:(UIApplication *)application
      {
          SKView* view = [self getSKViewSubview];
      
          if (view) {
              view.paused = NO;
          }
      
      }
      

      【讨论】:

        【解决方案4】:

        iPad 似乎可以后台运行,但 iPhone 在后台运行 sprite kit 游戏时肯定会崩溃。您必须手动执行此操作,自动魔法部分并不那么自动。

        【讨论】:

          【解决方案5】:

          SpriteKit 的文档确实还没有那么好,可能是因为它太新了,很少有开发人员实现它。 SpriteKit 应该在后台运行时暂停动画,但根据我的经验(和harrym17's),它会导致内存访问错误并完全退出应用程序而不是后台运行。

          根据 Apple 开发者论坛,这似乎是 SpriteKit 中的一个已知错误(它并不总是在后台暂停动画,因为它应该)导致memory access errors as per harrym17's comment。这是一个对我有用的简短修复 - 我的应用程序在后台运行时一直崩溃,并且自从添加此代码后一切正常。

          (感谢 Keith Murray 在 Apple 论坛上的代码;据我所知,他没有在 SO 上发布它)。

          AppDelegate.h,确保你导入了SpriteKit:

          #import <SpriteKit/SpriteKit.h>
          

          AppDelegate.m 中,编辑您的applicationWillResignActive 方法:

          - (void)applicationWillResignActive:(UIApplication *)application
          {
               // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
               // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
          
               // pause sprite kit
               SKView *view = (SKView *)self.window.rootViewController.view;
               view.paused = YES;
          }
          

          这是你的applicationDidBecomeActive 方法:

          - (void)applicationDidBecomeActive:(UIApplication *)application
          {
               // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
          
               // resume sprite kit
               SKView *view = (SKView *)self.window.rootViewController.view;
               view.paused = NO;
          }
          

          显然,在通过AVAudioSession 播放音频时,在后台运行时会出现其他问题;提到了一种解决方法in this thread

          【讨论】:

          • 这并不能防止崩溃(至少对我而言)
          • 优秀。我可以确认这行得通!如果您问我,这应该默认添加到任何 Sprite Kit 应用程序的 AppDelegate 中。此外,如果您在应用程序中使用声音,请将其与同一主题中的 AVAudioSession 修复结合起来。谢谢
          • 我还没有在这种情况下尝试过,但你也许可以使用 NSTimer(参见stackoverflow.com/questions/1449035/how-do-i-use-nstimer)。我已经使用 NSTimer 在应用程序激活时设置不同的变量,所以它应该适合你。
          • 太棒了!这是解决此问题的唯一解决方案。
          • 我爱你@MassivePenguin!几天来一直遇到这个问题,你的解决方案解决了我的问题。好开心!
          【解决方案6】:

          Sprite Kit 移动到后台时会自动暂停其动画计时器 - 您无需担心您的应用会因此而被杀死。

          【讨论】:

          • 但显然 iOS 终止了我的应用程序,原因是 EXC_BAD_ACCESS 但也显示 gpus_ReturnNotAllowedKillClient?
          • Sprite Kit 它会自动暂停动画计时器,但这肯定有问题。
          • 我在后台也收到了EXEC_BAD_ACCESS 错误 - 我的答案中的代码 似乎 已修复它,尽管我的应用程序目前确实没有那么复杂...
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-06-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多