播放 AVAudioPlayer 时游戏卡顿

Posted

技术标签:

【中文标题】播放 AVAudioPlayer 时游戏卡顿【英文标题】:Game lagging when AVAudioPlayer plays 【发布时间】:2016-07-15 17:57:57 【问题描述】:

我正在创建一个用户使用喷气背包控制角色的游戏。当喷气背包与钻石相交时,我将钻石加到它们的总数中,然后播放声音。但是,声音会使游戏暂停十分之一秒左右并打乱流程。这是我正在使用的代码:

var diamondSound = NSBundle.mainBundle().URLForResource("diamondCollect", withExtension: "wav")!
var diamondPlayer = AVAudioPlayer?()

    class GameScene: SKScene

      override func didMoveToView(view: SKView) 

            do 
                 diamondPlayer = try AVAudioPlayer(contentsOfURL: diamondSound)
                 guard let player = diamondPlayer else  return 

                 player.prepareToPlay()
             catch let error as NSError 
                 print(error.description)
            
       

然后:

    override func update(currentTime: CFTimeInterval) 

        if character.intersectsNode(diamond)
            diamondPlayer?.play()
            addDiamond()
            diamond.removeFromParent()
        

    

如果这很重要,我也在使用 Sprite Kit。非常感谢任何帮助!

【问题讨论】:

我会先尝试使用SKAudioNodeSKAction.playSoundWithFileNamed,因为它们是为与SpriteKit 一起使用而构建的。此外,您不需要警卫,因为您正在尝试捕获,我会删除它。如果从 AVAudioPlayer 返回 nil,它将触发 catch 我看到的问题是,您可能会多次触发播放,添加一个检查以仅播放一次,AVAudioPlayer 有一个 playing 布尔值,您可以检查 仅仅因为你从父节点中移除了diamond,并不意味着diamond已经死了,即使diamond不在场景中,你的intersectsNode仍然会通过 @Knight0fDragon 使用 SKAction.playSoundWithFile 效果很好!感谢您的帮助。 无论如何你可以测试我的游戏被多次调用理论吗?这样我就可以为你写一个正确的答案(切换到 SKAction 没有回答这个问题,其他人可能会遇到你的问题,用 AVAudioPlayer 寻找答案) 【参考方案1】:

通常,我更喜欢在我的游戏中使用SKAction.playSoundWithFile,但这有一个限制,没有音量设置。 所以,有了这个扩展,你就可以解决这个不足:

public extension SKAction 
  public class func playSoundFileNamed(fileName: String, atVolume: Float, waitForCompletion: Bool) -> SKAction 

    let nameOnly = (fileName as NSString).stringByDeletingPathExtension
    let fileExt  = (fileName as NSString).pathExtension

    let soundPath = NSBundle.mainBundle().URLForResource(nameOnly, withExtension: fileExt)


    var player: AVAudioPlayer! = AVAudioPlayer()
    do  player = try AVAudioPlayer(contentsOfURL: soundPath!, fileTypeHint: nil) 
    catch let error as NSError  print(error.description) 

    player.volume = atVolume

    let playAction: SKAction = SKAction.runBlock  () -> Void in
        player.prepareToPlay()
        player.play()
    

    if(waitForCompletion)
        let waitAction = SKAction.waitForDuration(player.duration)
        let groupAction: SKAction = SKAction.group([playAction, waitAction])
        return groupAction
    

    return playAction
  

用法

self.runAction(SKAction.playSoundFileNamed("diamondCollect.wav", atVolume:0.5, waitForCompletion: true))

【讨论】:

你为什么要经历这个麻烦,像我在 cmets 中提到的那样使用 SKAudioNode。你的方法有很多问题(这与 OP 相同,这就是我告诉他切换的原因)其中之一是如果你暂停精灵,你的音频仍然会播放 这不是麻烦,这是您可以使用的众多方法之一(例如,SKTAudio 库是另一个)。首先没有滞后所以回答OP问题,其次你必须区分背景音乐,效果器之间的音频。显然,扩展不能做你游戏的音频管理器。最好保持玩家参考和不止一个玩家。一个动作不仅可以从所涉及的精灵启动。这种方法可以用于小效果不能合理不需要暂停的情况下,否则你可以根据需要改进它以启用暂停。 有延迟,你的音频是在跑块发生后才准备好的,可能不会延迟游戏,但音频本身会延迟。我的观点是你正在创建一个扩展,它可以做 SKAudioNode 所做的事情,但效果很差。 SKAudioNodes 的行为几乎与动作相同,但不是向节点添加动作,而是添加一个子节点,归根结底是,您可以拿这个免费的水桶去取水,并且知道它可以盛水,或者您可以使用您的资源构建自己的存储桶并冒着泄漏的风险,因为您可能错过了一步 现实一点,SKAudioNode 仅适用于 ios 9,我无法接受 iOS 9 要求最低的解决方案,现在还为时过早。所以,恕我直言,SKAudioNode 仍然不能接受。 现实一点,

以上是关于播放 AVAudioPlayer 时游戏卡顿的主要内容,如果未能解决你的问题,请参考以下文章

触发 AVAudioPlayer 以停止所有声音并播放选定的声音,除非单击播放(选定)按钮

多任务处理后 AVAudioPlayer 继续播放

SpriteKit 游戏中的 AVAudioPlayer 和性能问题

iOS:将 AVAudioPlayer 的实例从一个变量移动到另一个变量

Swift AVAudioPlayer (Xcode) - 在应用程序包外播放音频文件

音量问题 - AVAudioPlayer 与 AudioServices 系统声音混合