【问题标题】:How to completely unload SpriteKit Scene如何完全卸载 SpriteKit 场景
【发布时间】: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 是的,我想到了,但我不确定要改变什么。

标签: ios sprite-kit skscene skview


【解决方案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场景没有完全卸载的问题。但是我在真机上测试,就没有这个问题了。
猜你喜欢
  • 2021-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-25
  • 2018-09-26
  • 2013-01-20
  • 2017-03-07
相关资源
最近更新 更多