SpriteKit SKTextureAtlas,加载纹理时由于内存压力而终止



类似于WWDC的SpriteKit特色游戏"Adventure",我尝试通过平铺加载我的背景图像。我创建了一个纹理图谱,其中包含6300个"瓷砖",每个瓷砖的大小为100x100像素。完整的背景图像总共为30000x2048(用于视网膜显示器)。其想法是背景将从右向左移动(侧滚动条)。第一列和最后一列匹配,使它们看起来连续。

当应用程序运行时,它会加载我的初始加载屏幕和标题图像,并在内存选项卡中达到54MB,CPU使用率为16%。这与我在菜单中导航一样,直到我选择我的级别,这告诉背景线程加载级别资产(其中包含前面提到的背景图像)。整个.atlas文件夹显示只有35.4MB。我不认为这是个问题,因为Adventure.atlas(来自WWDC)文件夹显示只有32.7MB

一旦我选择了级别,它就会在我开始接收内存警告之前将大约20个纹理加载到.atlas文件夹中,并导致应用程序崩溃。我已经检查了仪器的泄漏,它没有显示任何内存泄漏。我没有收到任何编译器错误(甚至没有EXC_BAD_ACCESS错误)。我查看了我的设备控制台,发现了应用程序崩溃的几行代码,但对我来说没有多大意义。我也检查了僵尸,但似乎没有发现。

CoreLevel.m

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
// Used to determine time spent to load
NSDate *startDate = [NSDate date];
// Atlas to load
SKTextureAtlas *tileAtlas = [SKTextureAtlas atlasNamed:@"Day"];
// Make sure the array is empty, before storing the tiles
sBackgroundTiles = nil;
sBackgroundTiles = [[NSMutableArray alloc] initWithCapacity:6300];
// For each row (21 Totals Rows)
for (int y = 0; y < 21; y++) {
// For each Column (100 Total Columns)
for (int x = 1; x <= 100; x++) {
// Get the tile number (0 * 32) + 0;
int tileNumber = (y * 300) + x;
// Create a SpriteNode of that tile
SKSpriteNode *tileNode = [SKSpriteNode spriteNodeWithTexture:[tileAtlas               textureNamed:[NSString stringWithFormat:@"tile_%d.png", tileNumber]]];
// Position the SpriteNode
CGPoint position = CGPointMake((x * 100), (y * 100));
tileNode.position = position;
// At layer
tileNode.zPosition = -1.0f;
tileNode.blendMode = SKBlendModeReplace;
// Add to array
[(NSMutableArray *)sBackgroundTiles addObject:tileNode];
}
}
NSLog(@"Loaded all world tiles in %f seconds", [[NSDate date] timeIntervalSinceDate:startDate]);
});

这似乎与来自调试控制台的崩溃有关:

com.apple.debugserver-300.2[9438] <Warning>: 1 +0.000000 sec [24de/1807]: error: ::read ( -1, 0x4069ec, 18446744069414585344 ) => -1 err = Bad file descriptor (0x00000009)
com.apple.debugserver-300.2[9438] <Warning>: Exiting.
com.apple.launchd[1] (UIKitApplication:tv.thebasement.Coin-Voyage[0x641d][9441]) <Notice>:     (UIKitApplication:tv.thebasement.Coin-Voyage[0x641d]) Exited: Killed: 9

我没有足够的声誉来发布图片,所以这里有一个链接到我在Instruments:中分配的屏幕截图

http://postimg.org/image/j17xl39et/

非常感谢您的帮助和建议!如果我遗漏了一些相关信息,我很乐意更新。

图像文件(PNG、JPG、图集文件夹等)的文件大小"不会告诉"您内存使用情况。

相反,你必须使用以下公式来计算纹理内存的使用情况:

width * height * (color bit depth / 8) = texture size in bytes

例如,尺寸为4096x4096像素、色深为32位(4字节)的图像在加载为纹理(未压缩)时会使用这么多内存:

4096 * 4096 * 4 = 67108864 bytes (64 Megabytes)

根据您的规格(6300个瓦片,每个100x100像素,假设它们都是唯一的),您的纹理内存使用量远远超过任何合理的限制(约1.5千兆字节!)。考虑到35兆字节的图集大小(对于图集btw来说,这是巨大的),并假设仅为10:1的压缩比,您可能仍然会看到350兆字节以上的纹理内存使用量。

最新更新