Ios SpriteKit纹理图谱与图像资源

Ios SpriteKit纹理图谱与图像资源,ios,sprite-kit,performance-testing,xcasset,texture-atlas,Ios,Sprite Kit,Performance Testing,Xcasset,Texture Atlas,我正在做一个游戏,我注意到在一些场景中,我的FPS在55-60FPS的范围内不断下降(使用纹理图谱)。这让我发疯,所以我决定把我所有的资源都放到Images.xcasets文件夹中,瞧,稳定的60帧 我认为这是一个侥幸,或者我做错了什么,所以我决定开始一个新项目,并执行一些基准测试 苹果的文档称,使用texture atlas将提高应用程序的性能。基本上,允许应用程序利用批渲染。然而 测试(): -(无效)运行测试 { SKAction*spawn=[SKAction运行块:^{ 对于(int

我正在做一个游戏,我注意到在一些场景中,我的FPS在55-60FPS的范围内不断下降(使用纹理图谱)。这让我发疯,所以我决定把我所有的资源都放到Images.xcasets文件夹中,瞧,稳定的60帧

我认为这是一个侥幸,或者我做错了什么,所以我决定开始一个新项目,并执行一些基准测试


苹果的文档称,使用texture atlas将提高应用程序的性能。基本上,允许应用程序利用批渲染。然而

测试():

-(无效)运行测试
{
SKAction*spawn=[SKAction运行块:^{

对于(int i=0;i首先,修改您的测试以匹配以下内容:

    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];

    }
这将允许您查看绘图计数,并正确了解SKTextureAtlas在何处提升性能

现在,不再只有一个图像,而是收集3个图像,并通过在每次创建节点时随机选择其中一个图像来修改测试,您可以这样做:

 NSArray *imageNames = @[@"image-0", @"image-1", @"image-2"];
 NSString *imageName = imageNames[arc4random() % imageNames.count];
在代码中,每次通过循环时都使用该imageName创建精灵。即:

SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithImageNamed:imageName];
在SKTextureAtlas测试中,显然使用相同的图像名称来创建每个精灵

现在…重新运行测试并记下每个测试中的抽签计数

这将为您提供一个使用SKTextureAtlas进行批渲染的具体示例

这与渲染同一个精灵图像数千次无关

它是关于在同一个绘制过程中绘制许多不同的精灵图像

在进行这种渲染优化时可能会有一些开销,但我认为绘制计数应该是不言自明的,因为在考虑所有因素时,为什么这种开销是没有意义的

现在,你可以假设更多:)

更新

正如评论中提到的,我的帖子是为了揭示为什么你的测试不是一个很好的测试,如果你想用一种有意义的方式来分析它,那么它是有缺陷的。你的测试就像用腮腺炎测试麻疹一样

下面是一个github项目,我将其放在一起,以确定SKTextureAtlas在哪些方面是合适的,并且确实优于xcassets

只需在设备上运行项目,然后点击在测试之间切换。您可以知道它何时使用SKTextureAtlas进行测试,因为绘图计数将为1,帧速率将为60fps

我隔离了将使用SKTextureAtlas进行优化的内容。这是一个60帧的动画,有1600个节点在播放该动画。我偏移了它们的开始帧,以便它们不会同时在同一帧上。我还为两个测试保持了所有内容的一致性,以便进行直接比较

如果有人认为使用SKTextureAtlas只会优化所有渲染,这是不准确的。它的优化是通过批渲染减少绘制计数来实现的。因此,如果帧速率降低不是通过批渲染可以改善的,那么SKTexture atlas是用于此项工作的错误工具。对吗

与对象池类似,您可以通过不不断创建和杀死游戏对象,而是从对象池中重用它们来获得优化。但是,如果您不不断创建和杀死游戏中的对象,池将不会优化游戏


根据我在讨论日志中看到的您描述为游戏问题的内容,在您的情况下,合用可能是工作的正确工具。

我想您没有亲自尝试过这一点?因为我在使用atlas时仍然表现不佳(大约5FPS的差异).Atlas 43FPS,xcassets以48FPS的速度使用3个随机图像。此外,在我最初的测试中,我选择不从父级删除,以查看性能如何随时间而恶化。无论如何,我可以看到批渲染的基本优点,不幸的是,如果您尝试重新绘制重复的精灵,那么它似乎伴随着太多的开销。我认为这可以追溯到假设2。如果您发现atlas超过xcassets的情况,请告诉我。我还注意到,如果您的atlas表充满了未使用的精灵。这几乎让人感觉它缓冲了整个工作表,只绘制了它需要的内容。我可能是错的,因为我不太确定atlas内部如何工作,但这是我最好的猜测。我确实尝试过。你做了一些不正确的事情。我在设备上获得了稳定的60fps。现在你说你“选择了”不从父级删除?:/恶化与批处理渲染无关,它与内存中数千个未被使用的节点有关。这是您的效率问题,而不是批处理渲染。因此不确定您为什么要使用它来基准批处理渲染。我向您展示了一个超过xcassets的场景,但似乎您不了解绘制计数是什么以及它对性能有什么影响。:/这是在模拟器上吗?、请发布设备规格、32位?64位?、金属支持设备?等等……我认为这个问题没有意义。您创建问题是因为误解了纹理图集的设计目的。这就像是在问,批量绘制是否更好S(纹理阿特拉斯)还是非批量绘制调用(XCASSET)?一种方法是考虑单个资产作为包含一个图像的纹理阿特拉斯。您最好的方法是研究纹理图集和如何正确使用纹理的最佳实践。
 NSArray *imageNames = @[@"image-0", @"image-1", @"image-2"];
 NSString *imageName = imageNames[arc4random() % imageNames.count];
SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithImageNamed:imageName];