可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Is there anyway to prevent SpriteKit from automatically unpausing a scene when entering foreground/becoming active?
I set paused = true
and want it to remain so even when the app becomes active again after having been sent to the background.
I should add that I'm doing this in swift, though I would not have expected the behaviour to be different in this regard.
回答1:
Not sure if it is the same in objective C, but in swift I had to "override" a callback function that SKView calls behind the scenes,
func CBApplicationDidBecomeActive()
{
}
This function was causing paused to be reset.
(note override keyword should not be applied)
In some cases where you want to just retain the state of pause, make a new variable instead and override the isPaused method.
class GameScene:SKScene
{
var realPaused = false
{
didSet
{
isPaused = realPaused
}
}
override var isPaused : Bool
{
get
{
return realPaused
}
set
{
//we do not want to use newValue because it is being set without our knowledge
paused = realPaused
}
}
}
回答2:
Pinxaton you are right but you can paused application by adding a small delay
(void)theAppIsActive:(NSNotification *)note
{
self.view.paused = YES;
SKAction *pauseTimer= [SKAction sequence:@[
[SKAction waitForDuration:0.1],
[SKAction performSelector:@selector(pauseTimerfun)
onTarget:self]
]];
[self runAction:pauseTimer withKey:@"pauseTimer"];
}
-(void) pauseTimerfun
{
self.view.paused = YES;
}
回答3:
this question may have been quite old, but I encountered the same problem today and I think I have found a pretty good solution to it:
In the AppDelegate, I do the following:
- (void)applicationDidBecomeActive:(UIApplication *)application
{
SKView *view = (SKView *)self.window.rootViewController.view;
if ([view.scene isKindOfClass:[GameScene class]])
{
XGGameScene *scene = (GameScene *)view.scene;
[scene resumeGame];
}
}
And then in the GameScene
class itself, I update a BOOL to reflect that the app has just resumed from background:
- (void)resumeGame
{
// Do whatever is necessary
self.justResumedFromBackground = YES;
}
And finally, in the update: loop, I run the following:
- (void)update:(NSTimeInterval)currentTime
{
// Other codes go here...
// Check if just resumed from background.
if (self.justResumedFromBackground)
{
self.world.paused = YES;
self.justResumedFromBackground = NO;
}
// Other codes go here...
}
Hope this helps!
回答4:
You should make use of your app delegate, specifically the applicationDidBecomeActive method. In that method send a notification that your SpriteKit view listens for.
So in the applicationDidBecomeActive method your code should look something like this:
// Post a notification when the app becomes active
[[NSNotificationCenter defaultCenter] postNotificationName:@"appIsActive" object:nil];
Now in your didMoveToView method in your SKScene file put the following:
// Add a listener that will respond to the notification sent from the above method
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(theAppIsActive:)
name:@"appIsActive" object:nil];
Then just add this method to your SKScene file:
//The method called when the notification arrives
(void)theAppIsActive:(NSNotification *)note
{
self.view.paused = YES;
}
回答5:
I made some adaptions to the solution from Knight0fDragon to make it work for me. This makes it so that isPaused will always be equal to realPaused. In order to pause the game, the "realPaused" variable should then only be altered, which changes automatically also the isPaused variable.
var realPaused: Bool = false {
didSet {
self.isPaused = realPaused
}
}
override var isPaused: Bool {
didSet {
if (self.isPaused != self.realPaused) {
self.isPaused = self.realPaused
}
}
}
Unfortunately, this will prevent the scene from pausing when the application is running in the background. In order to prevent that, I changed the condition to: "self.isPaused != self.realPaused && self.isPaused == false" so that the scene will still pause automatically when the app is put to the background but will only re-actiate if realPaused is also true:
var realPaused: Bool = false {
didSet {
self.isPaused = realPaused
}
}
override var isPaused: Bool {
didSet {
if (self.isPaused == false && self.realPaused == true) {
self.isPaused = true
}
}
}