2017-03-27 32 views
1

制作一个简单的精灵套件游戏。在那里,我听起来像按钮触摸声音等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 struct。在那里我有buttonTouchedAction(),我用它在不同的节点。我用一个“播放”按钮从我的菜单中放了一些代码。因此,例如,我在设备上运行游戏,显示菜单节点,等待几秒钟,然后点击按钮,在我的帧频下降后,我有一秒滞后,然后场景变为游戏场景。

+0

你能发布当你的按钮被“击中”时执行的代码吗? – Stoyan

+0

完成它斯托扬。用一些额外的代码编辑。 –

+0

'GameAudio'中是否存在错误的代码实现,比如使用四个'AVAudioPlayer()'来代替我的声音而不是一个?或者这没关系? –

回答

1

如果你想使用AVAudioPlayer(而不是SpriteKit's声音行动),你应该发出的声音在后台线程发挥,使得其操作不会与主线程干扰,所有的你的视觉的东西云:

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

但是,如果游戏后台我不想播放声音。 –

+1

@NurassylNuridin,他意味着后台线程。这与背景中的应用程序不同。你的应用程序通常运行在几个线程中,而你甚至不知道。例如,大多数SKA运行在不同的线程中。使用后台线程有助于将非时间关键型代码与FPS所依赖的代码分开。但是,正如我已经指出的那样,我认为这个问题与切换场景有关,而不是播放声音。例如,与设置AVAudioPlayers相比,我相信播放声音不会太昂贵。 – Stoyan

+0

当应用程序不再是由AVSession控制的应用程序时,游戏会播放声音。在我制作AVAudioPlayer在后台线程中播放(大部分是在较旧的iPad上)之前,我在自己的游戏中做了很短的渲染hic-ups,所以您应该尝试一下,以防万一您遇到同样的问题。 –

1

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

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

查看SKAction reference了解详情。

+0

我试过了,但我有[这个](http://stackoverflow.com/questions/42874601/my-app-crashes-because-of-unfinished-sounds-in-my-sprite-kit-game ) 问题。 –