SpriteKit 内存管理预加载缓存和 fps 问题

Posted

技术标签:

【中文标题】SpriteKit 内存管理预加载缓存和 fps 问题【英文标题】:SpriteKit memory management preload cached and fps issue 【发布时间】:2014-01-13 18:42:32 【问题描述】:

我的问题很简单,根据苹果文档,您可以在呈现这样的场景之前将纹理预加载到 RAM 中:

SKTextureAtlas * atlas = [SKTextureAtlas atlasNamed:@"effect_circle_explode"];
SKTextureAtlas * atlas2 = [SKTextureAtlas atlasNamed:@"box_explodes"];
SKTextureAtlas * atlas3 = [SKTextureAtlas atlasNamed:@"fence_new"];
SKTextureAtlas * atlas4 = [SKTextureAtlas atlasNamed:@"swipe"];
SKTextureAtlas * atlas5 = [SKTextureAtlas atlasNamed:@"coin"];
SKTextureAtlas * atlas6 = [SKTextureAtlas atlasNamed:@"two_times"];
SKTextureAtlas * atlas7 = [SKTextureAtlas atlasNamed:@"three_times"];
SKTextureAtlas * atlas8 = [SKTextureAtlas atlasNamed:@"gus"];

[SKTextureAtlas preloadTextureAtlases:@[atlas, atlas2, atlas3, atlas4, atlas5, atlas6, atlas7, atlas8] withCompletionHandler:^

    [moron_logo removeFromSuperview];
    moron_logo = NULL;

    stuff.hidden = NO;
    store.hidden = NO;

    scroll_view.userInteractionEnabled = YES;

    [self present_game_view];


];

如果以后在整个游戏过程中你也像这样调用同一个图集的预加载,现在会有任何负面影响:

-(void)load


SKTextureAtlas * atlas = [SKTextureAtlas atlasNamed:@"effect_circle_explode"];
SKTextureAtlas * atlas2 = [SKTextureAtlas atlasNamed:@"coin"];

[SKTextureAtlas preloadTextureAtlases:@[atlas, atlas2] withCompletionHandler:^

explode_textures = [[NSMutableArray alloc] init];
int numImages = (int)atlas.textureNames.count;
for (int i=0; i <= numImages/2-1; i++)

    NSString *textureName = [NSString stringWithFormat:@"effect_circle_explode_%d.png", i];
    SKTexture *temp = [atlas textureNamed:textureName];
    [explode_textures addObject:temp];


explodeAnimation = [SKAction animateWithTextures:explode_textures timePerFrame:.05];

idle_textures = [[NSMutableArray alloc] init];
int numImages2 = (int)atlas.textureNames.count;
for (int i=0; i <= numImages2/2-1; i++)

    NSString *textureName = [NSString stringWithFormat:@"coin_%d.png", i];
    SKTexture *temp = [atlas2 textureNamed:textureName];
    [idle_textures addObject:temp];



idleAnimation = [SKAction animateWithTextures:idle_textures timePerFrame:.05];

[self animate:0];

];



现在,如果我不再次预加载纹理,如果我只是将纹理直接插入 SKAction,游戏实际上会偶尔崩溃一次,而不是所有时间。崩溃是 Sprite::update(double) 调用上的 exec_bad_access,所以我的假设是第一次预加载的纹理以某种方式从 RAM 中删除,这就是我现在每次创建新节点时都预加载的原因。它似乎已经修复了这个错误。这导致了另一个问题,但是当涉及到性能时,这也是我问这个的原因。

游戏在 5S 和 5 上运行良好,但只要你触摸 iPod touch 第 5 代,它几乎无法超过 15 FPS。我运行了仪器,这就是占用所有 CPU 时间的原因: 这可能与我不断调用 preloadatlas 调用有关吗?有谁知道为什么这会在旧设备上严重消耗我的处理器时间?非常感谢,希望其他人可能会遇到类似的问题,一旦我深入了解,这将帮助他们。

提前致谢。

【问题讨论】:

【参考方案1】:

每次创建新精灵时都预加载图集通常是个坏主意。

您的实际问题似乎是您预加载了地图集,但没有保留它们。除非图集变量是全局变量。

一旦执行预加载的方法返回,atlas 对象现在将不再被引用,并将自动从内存中删除。 Sprite Kit 内部实现了一个缓存系统,因此您不会立即注意到它,但最终会消失一个或多个图集。

保持对场景中每个图集的强引用,以便图集保留在内存中,并在运行时停止预加载。我不知道这是否对 fps 有帮助。

【讨论】:

@LearnCocos2D 嗯,这是有道理的,出于某种原因,我认为它会自动知道将纹理保存在内存中。现在,当我加载纹理时,我应该没有任何问题。会尝试和你一起回来,非常感谢。 它修复了我所有与 exec 错误访问有关的错误,现在我没有泄漏任何内存,FPS 仍然存在问题,知道 CPU 上的那个进程到底是什么吗?我认为我的下一步将是使用在 preload 方法中加载的节点池,看看是否有帮助。 所以我也遇到了这个问题,我想我想澄清一下:现在要在地图集中加载 SKTextures,我只是将它们全部添加到 SKTextures 数组中,然后我正在使用 [SKTexture preload...],我得到了 exc_bad_acs 的东西...所以我应该切换到 [SKTextureAtlas preload 并删除 SKTexture 预加载吗?只要我将 SKTextureAtlas 设为一个属性,它就会一直存在?? @Cocorico 这就是为我做的。确保您对这些图集有很强的参考,这样您就不会再崩溃了。

以上是关于SpriteKit 内存管理预加载缓存和 fps 问题的主要内容,如果未能解决你的问题,请参考以下文章

FPS在SpriteKit中下降

在 SpriteKit 中预加载纹理

Glide:在内存缓存中预加载图像(有或没有磁盘缓存)

使用纹理图集时 SpriteKit 中的高内存使用率

在应用程序启动时将图像预加载到内存缓存中,使用 iOS 的 Objective c

在 Swift SpriteKit 中禁用节点和 FPS 标签