【问题标题】:Can't understand the lag in my spritekit game?无法理解我的 spritekit 游戏中的延迟?
【发布时间】:2017-08-20 14:09:05
【问题描述】:

制作一个简单的 spritekit 游戏。在那里,我听到了AVFoundation 声音库所做的按钮触摸声音等声音。但是有这个麻烦。按下任何按钮时,我的帧速率总是下降,这听起来。但是,如果我将所有声音都静音,则没有延迟。这是我的代码:

import AVFoundation

class GameAudio {
    static let shared = GameAudio()

    private var buttonClickSound = AVAudioPlayer()
    private var completionSound = AVAudioPlayer()
    private var swishSound = AVAudioPlayer()
    private var gridSwishSound = AVAudioPlayer()
    private let Volume: Float = 0.8

    func setupSounds() {
        print("GameAudio setupSounds()")
        if let path = Bundle.main.path(forResource: SoundNames.ButtonClickSoundName, ofType: "mp3") {
            let url = URL(fileURLWithPath: path )
            do {
                buttonClickSound = try AVAudioPlayer(contentsOf: url)
            } catch {
                print(error)
            }
        }
        if let path = Bundle.main.path(forResource: SoundNames.CompletionSoundName, ofType: "mp3") {
            let url = URL(fileURLWithPath: path)
            do {
                completionSound = try AVAudioPlayer(contentsOf: url)
            } catch {
                print(error)
            }
        }
        if let path = Bundle.main.path(forResource: SoundNames.SwishSoundName, ofType: "mp3") {
            let url = URL(fileURLWithPath: path )
            do {
                swishSound = try AVAudioPlayer(contentsOf: url)
            } catch {
                print(error)
            }
        }
        if let path = Bundle.main.path(forResource: SoundNames.GridSwishSoundName, ofType: "mp3") {
            let url = URL(fileURLWithPath: path)
            do {
                gridSwishSound = try AVAudioPlayer(contentsOf: url)
            } catch {
                print(error)
            }
        }
        buttonClickSound.volume = Volume
        completionSound.volume = Volume
        swishSound.volume = Volume
        gridSwishSound.volume = Volume
    }

    func playButtonClickSound() {
        buttonClickSound.play()
    }

    func playCompletionSound() {
        completionSound.play()
    }

    func playSwishSound() {
        swishSound.play()
    }

    func playGridSwishSound() {
        gridSwishSound.play()
    }
}

在我的 GameViewController 中,我调用 GameAudio.shared.setupSounds() 来预加载我所有的声音。

public struct Actions {
    static func buttonIsTouched(_ button: SKNode, sound: Bool, completion: @escaping () -> ()) {
        if button.hasActions() { return }
        if sound {
            GameAudio.shared.playButtonClickSound()
        }
        button.run(touchedButtonAction(scaleFactor: button.returnScaleFactor()), completion: completion)
    }
}

class MenuNode: SKNode {
    private let settings: Settings

    var delegate: MenuNodeDelegate?

    private let playButton = SKSpriteNode(imageNamed: SpriteNames.PlayButtonName)

    private let MenuNodeTreshold: CGFloat = 12.0

    init(settings: Settings) {
        self.settings = settings
        super.init()

        setupButtons()

        isUserInteractionEnabled = false
    }

    private func setupButtons() {
        playButton.position = CGPoint(x: 0.0 - playButton.frame.size.width / 2.0 - MenuNodeTreshold / 2.0, y: 0.0)
        addChild(playButton)
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        for touch in touches {
            let location = touch.location(in: self)

            if playButton.contains(location) {
                Actions.buttonIsTouched(playButton as SKNode, sound: settings.sound, completion: {
                    self.delegate?.playButtonTouched()
                })
            }
        }
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

我在游戏中的所有操作都使用Actions 结构。我有buttonTouchedAction(),我在不同的节点上使用它。我用一个“播放”按钮从我的菜单中添加了一些代码。因此,例如,我在设备上运行我的游戏,它显示菜单节点,等待几秒钟然后点击按钮,在我的帧速率下降之后,我有一秒钟的延迟,然后场景切换到游戏场景。

【问题讨论】:

  • 你能贴出当你的按钮被“点击”时执行的代码吗?
  • 完成了斯托扬。编辑了一些额外的代码。
  • GameAudio 中是否存在错误的代码实现,例如使用四个 AVAudioPlayer() 来代替我的声音?或者这样可以吗?
  • 您的 GameAudio 没问题。使用尽可能多的播放器 - 它只会影响内存使用。我认为您的 FPS 下降是由于切换场景,而不是来自播放实际声音。为了验证,只需删除切换场景的代码,并在播放声音时观察 FPS。切换场景时预期 FPS 下降是正常的,我还没有找到解决方法。
  • @Stoyan 但我只有一个场景并在两个节点之间切换 - MenuNodeGameNode,最后一个是我所有游戏内容的所在。在我的GameNode 中,我什至有这个问题,我点击形状,并且滞后在他的位置,没有切换任何节点。

标签: ios swift sprite-kit avfoundation lag


【解决方案1】:

我也有类似的问题。我最终使用SKAction 播放短音。

SKAction.playSoundFileNamed("Sounds/Click.wav", waitForCompletion: false)

详情请见SKAction reference

【讨论】:

  • 我已经尝试过了,但我遇到了this 问题。
【解决方案2】:

如果你想使用AVAudioPlayer(而不是SpriteKit's声音动作),你应该让声音在后台线程中播放,这样它的操作就不会干扰你所有视觉内容所在的主线程:

 let soundQueue = OperationQueue()
 soundQueue.qualityOfService = QualityOfService.background 
 soundQueue.addOperation{self.buttonClickSound.play()}

【讨论】:

  • 但是如果游戏进入后台我不想播放声音。
  • @NurassylNuridin,他的意思是后台线程。这与后台应用程序不同。您的应用程序通常在多个线程上运行,您甚至都没有注意到。例如,大多数 SKAction 在单独的线程中运行。使用后台线程有助于将非时间关键代码与 FPS 所依赖的代码分开。但是,正如我已经指出的那样,我认为问题与切换场景有关,而不是与播放声音有关。我相信与设置 AVAudioPlayers 相比,播放声音并不会太贵。
  • 当应用程序不再处于活动状态时游戏是否播放声音由您的 AVSession 控制。在我让 AVAudioPlayer 在后台线程中播放之前(主要在较旧的 iPad 上),我在自己的游戏中确实遇到过短暂的渲染问题,所以你应该尝试一下,以防你遇到和我一样的问题。
  • 我会试试这个!
  • 谢谢@AlainT。它对我有帮助!
猜你喜欢
  • 1970-01-01
  • 2010-09-07
  • 1970-01-01
  • 2011-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-18
  • 1970-01-01
相关资源
最近更新 更多