SKEmitterNode вызывает сбой при перезапуске сцены

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

1) Нажмите кнопку повтора и перейдите к той же сцене, в случайное время игра вылетает с ошибкой EXC_BAD_ACCESS.

2) Вернитесь на главный экран и нажмите «Играть» и перейдите к этой игровой сцене после смерти хотя бы один раз и создания узла-эмиттера.

В настоящее время SKEmitterNode является необязательной переменной класса. Когда игрок умирает, они устанавливают SKEmitterNode и прикрепляют его к сцене.

    // Add death smoke
    let smokePath: String = NSBundle.mainBundle().pathForResource("playerDeathSmoke", ofType: "sks")!
    self.deathSmokeEmitter = NSKeyedUnarchiver.unarchiveObjectWithFile(smokePath) as? SKEmitterNode
    self.deathSmokeEmitter?.name = "deathSmokeEmitter"
    if let deathEmitter = self.deathSmokeEmitter {
        deathEmitter.targetNode = self.scene
        self.addChild(deathEmitter)
    }

"self.addChild (deathEmitter)" вызовет сбой ПОСЛЕ перезагрузки сцены (дым ДЕЙСТВИТЕЛЬНО появляется). Точно так же код примера в документации SKEmitterNode добавляет узел эмиттера.

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

    override func removeFromParent() {
         self.deathSmokeEmitter?.removeFromParent()
         //self.deathSmokeEmitter?.targetNode = nil

         super.removeFromParent()
     }

После этого сбой будет происходить только при ВОЗВРАТЕ сначала на главный экран, а затем при переходе обратно в игровую сцену. Это означает, что я могу делать быстрые попытки снова и снова столько раз, сколько захочу, если это закомментировано, но он все равно вылетает, если я вернусь к домашней сцене и вернусь к сцене игры. Кроме того, когда он выходит из строя таким образом, трассировка стека показывает этот последний метод перед сбоем:

 [SKEffectNode dealloc]

Пожалуйста, дайте мне знать, если у вас есть идеи и спасибо!

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


person datWooWoo    schedule 20.06.2015    source источник
comment
Наверное, стоит посмотреть на утечки памяти в приборах. Ошибка, которую вы получаете, является результатом попытки доступа к переменной, которой нет.   -  person Andy Heard    schedule 20.06.2015
comment
Есть ли какие-нибудь инструкции для этого? Мне никогда не приходилось этого делать, и интерфейс инструментов довольно неинтуитивен. Я не смог найти никаких хороших руководств, в которых говорилось бы, что именно так вы обнаруживаете утечки памяти и исправляете их.   -  person datWooWoo    schedule 20.06.2015
comment
Я использовал руководство на raywenderlich.com пару дней назад, и это помогло мне найти пару утечек, которых я совсем не ожидал. Ему несколько лет, но выполнение шагов для вашего проекта должно немного помочь.   -  person Andy Heard    schedule 20.06.2015


Ответы (1)


Итак, я узнал, как это исправить (я в значительной степени понял это, когда задал вопрос), но для пояснения я напечатал это.

По какой-то причине SpriteKit в iOS 8 не удаляет излучатель дыма из спрайта Player при переключении сцен. Это каким-то образом вызывает сбой, поскольку по какой-то причине он пытается выполнить некоторую логику в следующей сцене.

То, что у меня было выше, было почти правильным. Сначала переопределите спрайт с помощью метода removeFromParent () дочернего эмиттера частиц следующим образом

// Sprite with ParticleEmitterNode child attached to it's method
override func removeFromParent() {
     self.deathSmokeEmitter?.removeFromParent()

     super.removeFromParent()
 }

Перед переключением сцен просто выполните spriteWithEmitterChild.removeFromParent (), чтобы удалить спрайт (с эмиттером в качестве дочернего) из сцены, который вызовет переопределенный метод и удалит эмиттер дыма из спрайта ПЕРЕД удалением спрайта со сцены.

person datWooWoo    schedule 30.06.2015