Утечка памяти набора фрагментов SpriteKit

Я пытаюсь создать двухмерную платформенную игру с помощью SpriteKit. В игре 21 уровень, то есть 21 сцена и 21 тайлсет. Каждая сцена содержит несколько узлов тайлов, каждый из которых использует только 1 набор тайлов. В какой-то момент я обнаружил, что моя игра потребляет почти 2 ГБ памяти и иногда прерывается из-за проблем с памятью.

Утечка памяти набора фрагментов SpriteKit

Я начал расследование причин этих утечек памяти с помощью инструментов. Я нашел 4 утечки, которые показаны на прикрепленном скриншоте. Ответственная библиотека — JavaScriptCore, я понятия не имею, что, черт возьми, это значит.

Утечка памяти набора фрагментов SpriteKit

Итак, я продолжаю расследование и пытаюсь удалить блоки кода и ресурсы из проекта, чтобы понять, что происходит.

В конце мой проект содержал:

  1. GameViewController, который выглядит точно так же, как GameViewController из шаблона XCode.
  2. Пустой подкласс SKScene
  3. 1 сцена
  4. 21 тайлсет

Код GameViewController:

class GameViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    if let scene = GKScene(fileNamed: "GameScene") {
        if let sceneNode = scene.rootNode as! SKScene? {
            sceneNode.scaleMode = .aspectFill
            if let view = self.view as! SKView? {
                view.presentScene(sceneNode)
                view.ignoresSiblingOrder = true
            }
        }
    }
}


override var shouldAutorotate: Bool {
    return true
}


override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    if UIDevice.current.userInterfaceIdiom == .phone {
        return .allButUpsideDown
    } else {
        return .all
    }
}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Release any cached data, images, etc that aren't in use.
}


override var prefersStatusBarHidden: Bool {
    return true
}

}

Таким образом, нет кода, который может вызвать утечку, и игра по-прежнему потребляет 2 ГБ в пиках. И только когда я удаляю из проекта все тайлсеты, кроме одного, который нужен для уровня - потребление памяти становится нормальным, около ~200мб.

Утечка памяти набора фрагментов SpriteKit

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

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

Мой вопрос в том, как правильно управлять этой ситуацией?

Спасибо!

Update1: график памяти прилагается Update2: предоставлен код GameViewController

Утечка памяти набора фрагментов SpriteKit

вы можете отладить график памяти и отследить эти фиолетовые '!'. Он подскажет откуда течь.

E.Coms 09.03.2019 16:05

Я тоже так сделал, график ничего полезного для меня не показывает. Скриншот графика прикрепил к сообщению.

acidbeast 09.03.2019 17:13

Без кода ваш вопрос эквивалентен сопению. Мы не телепаты.

Magnas 09.03.2019 18:04

Вы должны освободиться от всех этих розово-фиолетовых "!". Иногда, например, пропустил weak. Иногда вы вызываете системную функцию несовершенным образом. Но сначала попробуйте убрать все эти !.

E.Coms 09.03.2019 19:07

@Magnas Я обновляю пост с GameViewController, он действительно выглядит как GameViewController по умолчанию из игрового шаблона XCode SpriteKit.

acidbeast 09.03.2019 19:10

@E.Coms Да, я знаю о сильных и слабых ссылках. Когда я попытался воспроизвести проблему, я удалил весь свой код из проекта и вместо этого вставил GameViewController по умолчанию из игрового шаблона XCode SpriteKit, чтобы показать, что в проекте нет кода, который может вызвать утечку памяти.

acidbeast 09.03.2019 19:13

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

E.Coms 09.03.2019 19:15

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

acidbeast 09.03.2019 19:20

Вы знаете конкретную линию?

E.Coms 09.03.2019 19:28

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

E.Coms 09.03.2019 19:32

@E.Coms, к сожалению, утечки на графике не относятся к какой-либо строке кода или чему-то еще. :(

acidbeast 09.03.2019 20:03

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

E.Coms 09.03.2019 20:17

Тогда почему бы вам не попробовать программно прочитать узел плитки для каждого уровня?

El Tomato 10.03.2019 07:46

SKTileMapNode и окружающие его функции невероятно содержат ошибки. Я не удивлен, что у тебя проблемы с этим. У меня есть непосредственный опыт, и я могу сказать вам, что я бы рекомендовал держаться подальше от этого раздела SpriteKit. Вам будет намного проще написать весь свой собственный код для работы вместо SKTileMapNodes (и окружающих функций).

E. Huckabee 12.03.2019 09:57

@El Tomato Да, я переместил все узлы плитки в выделенный файл сцены и попытался загрузить этот файл программно, а затем переместить узлы в основную сцену. Но, к сожалению, все равно происходит утечка памяти именно тогда, когда я загружаю сцену с тайловыми узлами.

acidbeast 27.03.2019 06:49
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
15
187
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Попробуй это:

открыть Info.plist файл, добавить новую строку,

ключ: "Предпочитает OpenGL" тип: "булев" значение: "ДА"

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

MoDJ 27.05.2019 21:26
Ответ принят как подходящий

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

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