SpriteKit SKTextureAtlas, Завершено из-за давления памяти при загрузке текстуры
Как и в популярной игре SpriteKit "Приключение" от WWDC, я пытаюсь загрузить свое фоновое изображение с помощью плиток. Я создал текстурный атлас, который содержит 6300 "плиток" размером 100x100 пикселей каждая. Полное фоновое изображение - 30 000x2048 (для дисплеев сетчатки). Идея в том, что фон будет перемещаться справа налево (боковой скроллер). Первый и последний столбцы совпадают, поэтому они кажутся непрерывными.
Когда приложение запускается, оно загружает мой начальный экран загрузки и изображения заголовков и всплески до 54 МБ на моей вкладке памяти с использованием ЦП 16%. Это остается тем же самым, как я перемещаюсь по меню, пока я не выберу свой уровень, который сообщает фоновому потоку, чтобы загрузить активы уровня (из которых содержит вышеупомянутое фоновое изображение). Вся папка.atlas показывает только 35,4 МБ. Я не верю, что это проблема, поскольку папка Adventure .atlas (из WWDC) имеет размер всего 32,7 МБ.
После того, как я выбрал уровень, он загружает примерно 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]);
});
Вот что, похоже, относится к падению с консоли Debug:
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
У меня недостаточно репутации, чтобы размещать изображения, поэтому вот ссылка на скриншот с моим распределением в инструментах:
http://postimg.org/image/j17xl39et/
Любая помощь и совет высоко ценится! Если я пропустил некоторую соответствующую информацию, я рад обновить.
1 ответ
Размер файла изображения (PNG, JPG, папка Atlas и т. Д.) Ничего не говорит об использовании памяти.
Вместо этого вы должны рассчитать использование памяти текстуры по формуле:
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 мегабайт (что огромно для атласа между прочим) и допуская степень сжатия 10:1, вы все равно можете использовать 350+ мегабайт памяти текстур.