SpriteKit Texture Atlas vs Image xcassets

Estoy haciendo un juego y noté que durante algunas escenas, mi FPS siguió cayendo alnetworkingedor del área de 55-60FPS (usando atlas de textura). Esto me enloqueció, así que decidí poner todos mis resources en la carpeta Images.xcassets y voilá, 60FPS constante.

Pensé que esto era una casualidad o que estaba haciendo algo mal, así que decidí comenzar un nuevo proyecto y realizar algunos puntos de reference …


La documentation de Apple dice que usar texturas atlas mejorará el performance de la aplicación. Básicamente, permite que tu aplicación aproveche la renderización por lotes. Sin embargo…

La testing ( https://github.com/JRam13/JSGlitch ):

- (void)runTest { SKAction *spawn = [SKAction runBlock:^{ for (int i=0; i<10; i++) { SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithImageNamed:@"Spaceship"]; sprite.xScale = 0.5; sprite.yScale = 0.5; sprite.position = CGPointMake(0, [self randomNumberBetweenMin:0 andMax:768]); SKAction *action = [SKAction rotateByAngle:M_PI duration:1]; [sprite runAction:[SKAction repeatActionForever:action]]; SKAction *move = [SKAction moveByX:1200 y:0 duration:2]; [sprite runAction:move]; //notice I don't remove from parent (see test2 below) [self addChild:sprite]; } }]; SKAction *wait = [SKAction waitForDuration:.1]; SKAction *sequence = [SKAction sequence:@[spawn,wait]]; SKAction *repeat = [SKAction repeatActionForever:sequence]; [self runAction:repeat]; } 

Resultados:

introduzca la descripción de la imagen aquí

Las testings muestran repetidamente que el uso de los xcassets se realizó mucho mejor que la contraparte del atlas en FPS. Sin embargo, el atlas parece administrar la memory marginalmente mejor que las xcasassets.

¿Alguien sabe por qué estos resultados muestran que images.xcassets tiene un mejor performance que el atlas?


Algunas de las hipótesis que he propuesto son:

  • xcassets está mejor optimizado que atlasas.
  • Las atlas son buenas para dibujar muchas imágenes en un solo pase, pero tienen una sobrecarga más grande con repetidos sprites. Si es cierto, esto significa que si su sprite aparece varias veces en la pantalla (como fue el caso en mi juego original), es mejor eliminarlo del atlas.
  • Las hojas de atlas deben llenarse para optimizar el performance.

Actualizar

Para esta próxima testing, continué y quité el sprite del padre después de que se fuera de la pantalla. También usé 7 imágenes diferentes. Deberíamos ver una gran ganancia en el performance usando atlas debido al recuento de sorteos, pero …

introduzca la descripción de la imagen aquí

Primero, revisa tu testing para que coincida con esto:

  for (int i=0; i<10; i++) { SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithImageNamed:@"Spaceship"]; sprite.xScale = 0.5; sprite.yScale = 0.5; float spawnY = arc4random() % 768; sprite.position = CGPointMake(0, spawnY); SKAction *action = [SKAction rotateByAngle:M_PI duration:1]; [sprite runAction:[SKAction repeatActionForever:action]]; SKAction *move = [SKAction moveByX:1200 y:0 duration:2]; // next three lines replace the runAction line for move SKAction *remove = [SKAction removeFromParent]; SKAction *sequence = [SKAction sequence:@[move, remove]]; [sprite runAction:sequence]; [self addChild:sprite]; } 

Vuelva a ejecutar sus testings y notar que su framerate NUNCA se deteriora como en sus testings. Sus testings básicamente ilustraron lo que sucede cuando nunca quitas los nodos, sino que sigues creando otros nuevos.

A continuación, agregue la siguiente línea a su ViewController cuando configure su skview:

 skView.showsDrawCount = YES; 

Esto le permitirá ver el recuento de pliegos y comprender adecuadamente dónde obtendrá su aumento de performance con SKTextureAtlas.

Ahora, en lugar de tener una sola image, reúna 3 imágenes y modifique su testing eligiendo una aleatoria de esas imágenes cada vez que cree un nodo, puede hacer algo como esto:

  NSArray *imageNames = @[@"image-0", @"image-1", @"image-2"]; NSString *imageName = imageNames[arc4random() % imageNames.count]; 

En su código, cree su sprite con ese nombre de image cada vez a través del ciclo. es decir:

 SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithImageNamed:imageName]; 

En su testing SKTextureAtlas, use ese mismo imageName obviamente para crear cada sprite.

Ahora … vuelva a ejecutar sus testings y tome nota del recuento de tablas en cada testing.

Esto debería darle un ejemplo tangible de qué trata el procesamiento por lotes con SKTextureAtlas.

No se trata de representar la misma image de sprite miles de veces.

Se trata de dibujar muchas imágenes de sprites diferentes en el mismo pase de sorteo.

Es probable que haya una sobrecarga en la obtención de esta optimization de la representación, pero creo que el recuento de ttwigs debe ser explicativo de por qué esa sobrecarga es discutible cuando se consideran todas las cosas.

Ahora, puedes hipotetizar más 🙂

ACTUALIZAR

Como se mencionó en los comentarios, mi publicación fue para exponer por qué su testing no fue una buena testing para los beneficios de SKTextureAtlas y fue defectuosa si buscaba analizarla de manera significativa. Su testing fue como una testing de sarampión con una testing de paperas.

A continuación se muestra un proyecto github que puse para identificar dónde es apropiado un SKTextureAtlas y, de hecho, superior a xcassets.

comparación de atlas

Simplemente ejecuta el proyecto en tu dispositivo y luego toca para alternar entre testings. Puedes saber cuándo está probando con SKTextureAtlas porque el conteo de sorteos será 1 y el framerate será 60fps.

Aislé lo que se optimizará con un SKTextureAtlas. Es una animation de 60 cuadros y 1600 nodos reproduciendo esa animation. Compensé sus frameworks iniciales para que no todos estén en el mismo marco al mismo time. También mantuve todo uniforme para ambas testings, por lo que es una comparación directa.

No es exacto para alguien pensar que usar SKTextureAtlas simplemente optimizará todo el renderizado. Su optimization viene networkinguciendo el número de sorteos mediante procesamiento por lotes. Por lo tanto, si la ralentización de la velocidad de fotogtwigs no es algo que se puede mejorar mediante la representación por lotes, el atlas de SKTexture es la herramienta incorrecta para el trabajo. derecho ?

Similar al agrupamiento de objects, donde puede get la optimization a través de no crear y matar a los objects del juego constantemente, sino que los reutiliza en un grupo de objects. Sin embargo, si no estás constantemente creando y matando objects en tu juego, la agrupación no optimizará tu juego.

Según lo que vi que describes como el problema de su juego en el logging de discusión, la agrupación es probablemente la herramienta adecuada para el trabajo en su caso.