У SpriteKit огромное снижение производительности при чистке SKTextureAtlas

У меня очень странная проблема при очистке кэшированного экземпляра SKTextureAtlas,

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

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

проблема

У меня проблема в том, что когда я очищаю текстурный атлас (устанавливая свойство, которое содержало ссылку на атлас, nil), производительность резко падает в течение нескольких секунд. Под радикальным пониманием я подразумеваю постоянную скорость от 60 до 40 кадров в секунду.

Обратите внимание, что на данный момент нет никаких других ссылок на этот атлас.


Интересно: часть 1

Это происходит только на iOS 10. Отлично работает на iOS 9, даже на более старых устройствах.

Интересно: часть 2

Бывает только если атлас определен в форме .spriteatlas внутри .xcassets, но не если атлас .atlas папка за пределами .xcassets,

Я знаю, я мог бы просто пойти дальше и использовать .atlas вместо .spriteatlas , но .spriteatlas поддержка приложения-прореживания из коробки, которая .atlas не делает.

Интересно: часть 3

Очистка работает хорошо, если в атласе небольшое количество небольших текстур. Это указывает на то, что может быть внутренняя проблема, связанная с общим размером атласа. Но почему?

мотивация

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

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

Любая помощь будет оценена.


Обновить

Я попытался реализовать решение, предложенное @Knight0fDragon, которое предлагает кеширование SKTexture с из SKTextureAtlas вместо SKTextureAtlas само по себе, но это, к сожалению, не сработало в моем случае.

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


Решение

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

Проблема заключалась в анимации в фоновом режиме. Эта анимация была настроена так

let rotation = CABasicAnimation(keyPath: "transform.rotation")
rotation.fromValue = 0
rotation.toValue = 2 * M_PI
rotation.duration = 110
rotation.repeatCount = Float.infinity

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

Переход между этими двумя контроллерами представления является пользовательским, и, поскольку я забыл добавить вызовы в beginAppearanceTransition а также endAppearanceTransition в пользовательском аниматоре перехода методы жизненного цикла контроллера представления (viewWillAppear:, viewWillDisappear) не были вызваны, именно там у меня была логика для запуска / остановки всех анимаций. Поэтому анимация продолжалась в фоновом режиме.

Тем не менее, даже если анимация работала в фоновом режиме, она не должна мешать чему-то совершенно не связанному, например очистке кэшированного атласа.

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

0 ответов

Другие вопросы по тегам