如何完全卸载 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 场景的主要内容,如果未能解决你的问题,请参考以下文章
Swift:Spritekit 中的多个场景,从第二个和第一个场景的不同 Sprite 节点类型调用 touchesBegan