Проблемы с FPS при добавлении размытия с помощью SKEffectNode

Есть ли лучший способ создать эффект размытия? Похоже, то, как я сейчас это делаю, создает проблемы с FPS, особенно на старых телефонах. Похоже, что чем выше BlurAmount, тем ниже FPS. Может ли здесь быть причиной blendMode?

        if effectsNode.parent == nil {
            let filter = CIFilter(name: "CIGaussianBlur")
            let blurAmount = 15.0
            filter!.setValue(blurAmount, forKey: kCIInputRadiusKey)

            effectsNode.filter = filter
            effectsNode.blendMode = .add

            sceneContent.removeFromParent()
            effectsNode.addChild(sceneContent)
            addChild(effectsNode)
        }

Когда я приостанавливаю свою игру, я вызываю blurScreen(), который выполняет следующий код выше. Тем не менее, кажется, что мой fps со временем падает, чем дольше игра стоит на паузе. Я попытался отключить blurScreen(), и проблемы с FPS исчезли. Как со временем падает FPS, когда blurScreen() вызывается только один раз?

РЕДАКТИРОВАТЬ:

func pauseGame() {
    sceneContent.isPaused = true
    intermission = true

    physicsWorld.speed = 0

    blurScreen()
} 

Вот код в touchesEnded()

// Tapped pause or pause menu options
if name == "pause" && touch.tapCount == 1 && pauseSprite.alpha == 1.0 && ((!sceneContent.isPaused && !GameData.shared.midNewDay) || (!sceneContent.isPaused && sceneElements[0].editingMode)) {
                    SKTAudio.sharedInstance.pauseBackgroundMusic()
                    SKTAudio.sharedInstance.playSoundEffect("Sounds/pause.wav")

                   pauseSprite.run(SKAction.sequence([SKAction.scale(to: 1.2, duration: 0.10), SKAction.scale(to: 1.0, duration: 0.10)])) { [unowned self] in
                        self.createPauseMenu()
                        self.pauseGame()
                    }

                    return
                }

Метод обновления

override func update(_ currentTime: TimeInterval) {
    if GameData.shared.firstTimePlaying && GameData.shared.distanceMoved > 600 && !step1Complete {
        tutorial2()
    }

    // Check for game over
    if GameData.shared.hearts == 0 && !gameEnded {
        gameOver()
    }

    // If we're in intermission, do nothing
    if intermission || sceneContent.isPaused {
        return
    }

    // some more stuff unrelated to pausing
}

person Brejuro    schedule 27.10.2017    source источник
comment
Нам нужно увидеть больше кода, однократное размытие не должно вызывать замедления, но размытие в цикле обновления будет   -  person Knight0fDragon    schedule 27.10.2017
comment
Кроме того, вы всегда можете сделать размытие в фоновом потоке, а когда закончите, добавить его в родительский поток в основном потоке.   -  person Knight0fDragon    schedule 27.10.2017
comment
@Knight0fDragon Спасибо за ответ! Я тоже так думал, я добавил еще немного кода, связанного с паузой   -  person Brejuro    schedule 27.10.2017
comment
о, вы размываете всю сцену, да, это будет медленно. Обязательно поместите это в фоновую тему   -  person Knight0fDragon    schedule 27.10.2017
comment
кстати, сцена - это SKEffectNode, поэтому вы должны иметь возможность применять размытие непосредственно к ней.   -  person Knight0fDragon    schedule 27.10.2017
comment
@Knight0fDragon Знаете ли вы, как я это сделаю, или где-нибудь я могу об этом прочитать? Я мало что сделал, используя фоновые потоки. Также я размываю содержимое SKNode с именем sceneContent, который содержит все узлы, которые мне нужно размыть, поэтому я добавляю sceneContent к EffectsNode и размываю его. Есть некоторые узлы, которые не следует размывать, поэтому я не размываю всю сцену.   -  person Brejuro    schedule 27.10.2017
comment
о, я понял, пауза — это оверлейный узел. хм без понятия, но код DispatchQueue.global(qos:.background).async{...do code ... DispatchQueue.main.async{..do stuff needed on main thread}}   -  person Knight0fDragon    schedule 27.10.2017
comment
@Knight0fDragon Я собираюсь посмотреть, как выполнять задачи в фоновом потоке. Как вы думаете, это решит проблему с FPS?   -  person Brejuro    schedule 27.10.2017
comment
Да, я думаю, я не вижу каких-либо серьезных недостатков в вашем коде (хотя я не поклонник того, что вы делаете так много ветвлений в своей функции обновления, вы должны избавиться от этой привычки). Вам просто нужно убедиться, что вы не делать что-либо во время создания эффекта.   -  person Knight0fDragon    schedule 27.10.2017
comment
Давайте продолжим обсуждение в чате.   -  person Brejuro    schedule 27.10.2017


Ответы (1)


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

var spriteScene : SKSpriteNode!
func blurScreen() { 
    DispatchQueue.global(qos: .background).async { 
        [weak self] in
        guard let strongSelf = self else { return }
        let effectsNode = SKEffectNode() 

        let filter = CIFilter(name: "CIGaussianBlur") 
        let blurAmount = 10.0 
        filter!.setValue(blurAmount, forKey: kCIInputRadiusKey) 

        effectsNode.filter = filter 
        effectsNode.blendMode = .add 

        strongSelf.sceneContent.removeFromParent() 
        effectsNode.addChild(strongSelf.sceneContent) 

        let texture = self.view!.texture(from: effectsNode) 
        strongSelf.spriteScene = SKSpriteNode(texture: texture) 
        strongSelf.spriteScene.anchorPoint = CGPoint(x: 0.5, y: 0.5) 

        DispatchQueue.main.async { 
            strongSelf.sceneContent.removeFromParent() 
            strongSelf.addChild(strongSelf.spriteScene) 
        } 
    } 
} 
person Knight0fDragon    schedule 27.10.2017