Подтвердить что ты не робот

SpriteKit Texture Atlas vs Image xcassets

Я делаю игру, и я заметил, что во время некоторых сцен мой FPS продолжал падать вокруг области 55-60FPS (используя текстурный атлас). Это заставило меня замочить, поэтому я решил поместить все свои активы в папку Images.xcassets и voila, установив 60FPS.

Я думал, что это была случайность или что я делал что-то неправильно, поэтому я решил начать новый проект и выполнить некоторые тесты...


В документации Apple говорится, что использование текстурного атласа улучшит производительность приложения. В принципе, это позволяет вашему приложению использовать пакетный рендеринг. Однако...

Тест (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];
}

Результаты:

enter image description here

Тесты неоднократно показывают, что использование xcassets выполняется лучше, чем контраст атласа в FPS. Кажется, что атлас управляет памятью немного лучше, чем xcassets.

Кто-нибудь знает, почему эти результаты показывают, что изображения .xcassets имеют лучшую производительность, чем атлас?


Некоторые гипотезы, которые я придумал:

  • xcassets лучше оптимизирован, чем атласы.
  • atlasas хороши при рисовании большого количества изображений в одном проходе ничьей, но имеют большие накладные расходы с повторяющимися спрайтами. Если это правда, это означает, что если ваш спрайт появляется несколько раз на экране (что было в моей оригинальной игре), лучше удалить его из атласа.
  • атласные листы должны быть заполнены для оптимизации производительности

Обновление

Для этого следующего теста я пошел вперед и удалил спрайт из родителя после его выхода на экран. Я также использовал 7 разных изображений. Мы должны увидеть огромный прирост производительности, используя атлас из-за подсчета ничьей, но...

enter image description here

4b9b3361

Ответ 1

Сначала перейдите в свой тест, чтобы он соответствовал этому:

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

    }

Повторите свои тесты, и вы должны заметить, что частота кадров никогда не ухудшается, как в ваших тестах. Ваши тесты в основном иллюстрируют, что происходит, когда вы никогда не удаляете узлы, но продолжайте создавать новые.

Затем добавьте следующую строку в свой ViewController при настройке своего skview:

skView.showsDrawCount = YES;

Это позволит вам увидеть счетчик обращений и правильно понять, где вы получаете повышение производительности с помощью SKTextureAtlas.

Теперь вместо того, чтобы иметь только одно изображение, соберите 3 изображения и измените свой тест, выбирая случайное одно из этих изображений каждый раз, когда он создает node, вы можете сделать это примерно так:

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

В своем коде создайте свой спрайт с этим именем образа каждый раз через цикл. т.е.:

SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithImageNamed:imageName];

В вашем тесте SKTextureAtlas используйте то же самое изображениеName, чтобы создать каждый спрайт.

Теперь... повторите свои тесты и обратите внимание на количество обращений в каждом тесте.

Это должно дать вам ощутимый пример того, что представляет собой пакетный рендеринг с помощью SKTextureAtlas.

Это не означает, что тысячи раз создавали одно и то же изображение спрайта.

Это о том, как рисовать много разных изображений спрайтов в одном и том же проходе.

Вероятно, некоторые издержки на получение этой оптимизации рендеринга, но я думаю, что счетчик обращений должен быть самоочевидным относительно того, почему эти накладные расходы являются спорными, когда все вещи рассматриваются.

Теперь вы можете предположить еще несколько:)

UPDATE

Как упоминалось в комментариях, мой пост заключался в том, чтобы разоблачить, почему ваш тест не был хорошим испытанием для преимуществ SKTextureAtlas и был испорчен, если вы хотите проанализировать его значимым образом. Ваш тест был похож на тестирование на корь с помощью теста на свинке.

Ниже представлен проект github, который я собрал, чтобы определить, где SKTextureAtlas подходит и действительно превосходит xcassets.

атлас-сравнение

Просто запустите проект на своем устройстве, а затем нажмите, чтобы переключаться между тестами. Вы можете сказать, когда он тестируется с помощью SKTextureAtlas, потому что счетчик обращений будет равен 1, а частота кадров будет 60 кадров в секунду.

Я выделил то, что будет оптимизировано с помощью SKTextureAtlas. Это 60 кадров анимации и 1600 узлов, играющих эту анимацию. Я компенсировал их начальные кадры, чтобы они все не были в одном и том же кадре одновременно. Я также сохранил все единообразные для обоих тестов, так что это прямое сравнение.

Неверно кому-то думать, что использование SKTextureAtlas просто оптимизирует весь рендеринг. Оптимизация достигается за счет уменьшения количества счетчиков путем пакетной рендеринга. Таким образом, если ваше замедление кадров не является чем-то, что можно улучшить с помощью пакетного рендеринга, атлас SKTexture является неправильным инструментом для работы. прав?

Подобно объединению объектов, где вы можете получить оптимизацию, не создавая и убивая ваши игровые объекты постоянно, а вместо этого повторно используя их из пула объектов. Однако, если вы не постоянно создаете и убиваете объекты в своей игре, объединение не собирается оптимизировать вашу игру.

Основываясь на том, что я видел, вы описываете как свою проблему с игрой в журнале обсуждения, возможно, пул - это правильный инструмент для работы в вашем случае.