У 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
) не были вызваны, именно там у меня была логика для запуска / остановки всех анимаций. Поэтому анимация продолжалась в фоновом режиме.
Тем не менее, даже если анимация работала в фоновом режиме, она не должна мешать чему-то совершенно не связанному, например очистке кэшированного атласа.
Примечание: изображение в представлении изображения с проблемной анимацией не было определено в атласе проблемной текстуры.