如何完全卸载 SpriteKit 场景

Posted

技术标签:

【中文标题】如何完全卸载 SpriteKit 场景【英文标题】:How to completely unload SpriteKit Scene 【发布时间】:2014-05-01 05:29:54 【问题描述】:

当我在游戏中点击重试按钮时,我希望它重新加载 MainScene。我正在这样做:

-(void)retry

    SKTransition *transition = [SKTransition fadeWithDuration:.4];
    MainScene *gameOver = [[MainScene alloc] initWithSize:self.size];
    [gameOver didMoveToView:self.view];
    [self.scene.view presentScene:gameOver transition:transition];

但是,每次我点击重试时,这都会导致内存/CPU 使用率增加(很多)。大约重试 10-20 次后,会有明显的延迟。

我将我的所有 SKEmitterNode 和 SKSpriteNode 都设为静态并修复了内存问题,所以我怀疑我的精灵、发射器等没有从内存中释放,并且每次重试时都会重新加载,使其翻倍。

我正在像这样加载精灵/发射器:

@implementation MainScene 
    SKEmitterNode *_bubbleEmitter;
    SKSpriteNode *_sunglasses;
    ...


- (id)initWithSize:(CGSize)size

  if (self = [super initWithSize:size]) 
  
     _sunglasses = [SKSpriteNode spriteNodeWithImageNamed:@"sunglasses"];
     [_sunglasses setPosition:CGPointMake(self.size.width/2,  self.size.height + 10)];
     [self addChild:_sunglasses];

     ...
  
  return self;

我是加载精灵还是重试错误?

【问题讨论】:

@ElTomato 是的,我想到了,但我不确定要改变什么。 【参考方案1】:

这可能是也可能不是原因,但是自己调用这个方法肯定是错误的:

[gameOver didMoveToView:self.view];

didMoveToView: 方法在您呈现场景时由 SKView 发送到场景。这意味着这个方法实际上会运行两次。

还可以通过实施来验证您的场景是否正确释放:

-(void) dealloc

    NSLog(@"dealloc: %@", self);

查看日志或设置断点以确认场景已解除分配。如果不是,请检查内存泄漏和保留周期。

【讨论】:

我不知道为什么会有这段代码,可能是因为测试了不同的东西。 Dealloc 没有被调用,但我不知道为什么。有一个很小的内存泄漏,但它与我读到的 CGPath 只是物理体的一个错误有关。是否有其他原因导致无法调用 dealloc? 保留循环,检查对场景的任何强引用,以及任何对父节点或兄弟节点保持强引用的节点(那些应该是弱的)。此外,您创建的 CGPath 对象在使用/分配后也必须是您的 CGPathRelease(path),这可能不是 Sprite Kit 的问题。 宾果游戏!原来,一个 NSTimer 仍在运行,需要失效。正在调用 Dealloc,问题就消失了。差不多了,似乎还有一点内存泄漏,但主要问题已经消失了:)谢谢! 不要将 NSTimer 用于 Sprite Kit 中与时间相关的任何事情!使用 SKScene 的更新方法。 NSTimer 可能会在更新循环中的未确定时间触发,而且如果您暂停/转换节点或场景,它们也不会暂停。 ios 8中,使用Swift实现,我在模拟器中发现SpriteKit场景没有完全卸载的问题。但是我在真机上测试,就没有这个问题了。

以上是关于如何完全卸载 SpriteKit 场景的主要内容,如果未能解决你的问题,请参考以下文章

如何在场景中放置场景 - Sprite Kit

为啥我的音频会在 Sprite Kit 场景转换之前播放?

Swift:Spritekit 中的多个场景,从第二个和第一个场景的不同 Sprite 节点类型调用 touchesBegan

iOS7 + Sprite Kit:如果我正在改变场景,如何保持一个计时器一直显示?

如何最好地在SpriteKit中编写撤销功能?

Sprite Kit 最后得分数据