【问题标题】:Caching large texture atlas for use with animation in swift and spritekit缓存大型纹理图集以用于 swift 和 spritekit 中的动画
【发布时间】:2015-04-07 19:22:30
【问题描述】:

我无法缓存大型纹理图集(几乎是完整的 2048x2048)并将其用于带有纹理的动画。它最初在第一次加载时滞后。之后就可以了。对于我所有其他的地图集,我只是将它们放在一个单例中,并使用以下链接中的方法保存它们:https://www.codeandweb.com/blog/2013/09/23/spritekit-animations-and-textureatlases self.atlas = [SKTextureAtlas atlasNamed:SPRITES_ATLAS_NAME]

似乎它正在加载然后卸载内存中的纹理图集。有没有其他人经历过这个? 使用 Swift 1.2、SpriteKit、Texture Packer

【问题讨论】:

  • 你应该更准确。纹理有多大,您在地图集中存储了多少?你的动画有多快(timePerFrame)?您是否尝试隔离使用纹理制作动画的代码,以确保没有其他东西会导致初始滞后(声音会在初始加载时产生滞后)。 stackoverflow.com/questions/28041605/…
  • 如果您不保留对它的引用,SK 可能会决定将其从内存中转储。
  • 感谢您的回复。每个纹理的大小为 640x640,共有 39 个单独的纹理。它们被设计成适合一张 2048x2048 的纸张,并且边缘周围有很多空白空间。即使我不调用动画而只是尝试使用其中一种纹理,它仍然会出现初始滞后。我以 swift 1.2 的方式在单例中保留对它的引用。类 GameTextures { 静态让 sharedInstance = GameTextures(); var 爆炸图集:SKTextureAtlas; } init() {self.explosionAtlas = SKTextureAtlas(named: "Explosion")}
  • 不要使用单例,这种设计模式定义为内存泄漏。将 SKTexture 的引用挂在场景之外,并根据场景实现加载/卸载。让 SpriteKit 管理当前加载的图集,并专注于减少应用程序中实际纹理的内存使用。您看到的加载时间是原始 PNG 被解码然后变成未压缩的纹理时,您将无法解决这个问题。
  • 进一步仅供参考,您可能想看看这里提到的示例,其中包括一个非常大的 SpriteKit Fire 动画,它使用 32BPP 的 1000x1000 动画:stackoverflow.com/questions/22470907/…

标签: sprite-kit


【解决方案1】:

我最终找到了解决方案。您所要做的就是在运行前向场景中添加一个项目,以确保它解压缩了图集。我编写了一个函数来对 atlas/texture 控制器中的所有图集执行此操作。苹果表示没有内置函数可以做到这一点,preload函数不会执行解压。

【讨论】:

    【解决方案2】:

    通过在 GameTextures 类中使用 Singleton 模式,您可能只是避免 self.explosionAtlas 被初始化两次。但我认为你实际上并没有预加载纹理。您必须先预加载它们,然后通过像@sangony 指出的那样对它们进行强引用来防止它们被释放。像self.explosionAtlas 这样存储引用不会自动将纹理从该图集预加载到内存中。当您手动将纹理预加载到数组中或使用像 + preloadTextureAtlases:withCompletionHandler: 这样的方法时,您可以通过查看内存消耗在调试导航器中检查这一点,而不是像 self.atlas = [SKTextureAtlas atlasNamed...]

    我会做的一件事是完全删除与该动画相关的代码,以查看应用程序在呈现场景时是否在启动时滞后。只是为了确定问题出在哪里。

    还要检查您的 timePerFrame 参数...不要将其设置得太低...如果您使用 39 张图像仅用于一次爆炸,我认为您应该尝试使用更少的帧并将 timePerFrame 参数设置为更高的值。我有 10 张图片,timePerFrame 设置为 0.06,但看起来仍然很棒。您当然知道设备的内存有限...iPhone 4s 有 512 MB 的 RAM 内存,但是当内存消耗约为 200 - 250 MB 时它会崩溃。所以要小心大动画/纹理,因为纹理会消耗大部分应用程序的内存。 Check this out

    要计算多少图像将进入内存,您可以阅读here

    请注意,如果您决定放弃当前的动画,则可以使用 SKEmitterNode 进行大爆炸,但我仍然认为您没有正确缓存纹理,并且在调用动画之前它们还没有准备好(以及您正在使用 small timePerFrame 间隔,例如 0.033 或类似的值)。

    希望这会带你到某个地方。

    【讨论】:

      【解决方案3】:

      如果您使用单例来存储所有动画,我建议您考虑这些示例来组织它。

      单例头文件

      -(void)loadPlayer0Atlas;
      @property (strong) SKTextureAtlas *player0Atlas;
      @property (strong) SKAction *player0_walk;
      @property (strong) SKAction *player0_jump;
      @property (strong) SKAction *player0_shoot;
      

      单例实现文件

      -(void)loadPlayer0Atlas {
          if(self.player0Atlas == nil) {
              NSLog(@"loading player0AtlasLoaded");
              self.player0Atlas = [SKTextureAtlas atlasNamed:PLAYER0ATLAS_ATLAS_NAME];
              [SKTextureAtlas preloadTextureAtlases:[NSArray arrayWithObject:self.player0Atlas] withCompletionHandler:^{
                  [self loadPlayer0Assets];
              }];
          } else {
              NSLog(@"no load needed for player0AtlasLoaded");
              [[NSNotificationCenter defaultCenter]postNotificationName:@"player0AtlasLoaded" object:self];
          }
      }
      
      -(void)loadPlayer0Assets {
          self.player0_walk = [SKAction repeatActionForever:[SKAction animateWithTextures:PLAYER0ATLAS_ANIM_WALK timePerFrame:0.1]];
          self.player0_jump = [SKAction animateWithTextures:PLAYER0ATLAS_ANIM_JUMP timePerFrame:0.05];
          self.player0_shoot = [SKAction repeatActionForever:[SKAction animateWithTextures:PLAYER0ATLAS_ANIM_SHOOT timePerFrame:0.1]];
          [[NSNotificationCenter defaultCenter]postNotificationName:@"player0AtlasLoaded" object:self];
      }
      

      强大的类属性保留对您的图集和动画的引用。您可以调用 loadPlayer0Atlas 方法来加载图集和动画。加载后,会发送一条 NSNotification 消息,让您在(例如)GameScene 中知道。

      你可以这样调用动画:

      [playerNode runAction:[singleton player0_walk] withKey:@"animation"];
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-22
        • 2014-11-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多