播放 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。非常感谢任何帮助!
【问题讨论】:
我会先尝试使用SKAudioNode
或SKAction.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 以停止所有声音并播放选定的声音,除非单击播放(选定)按钮
SpriteKit 游戏中的 AVAudioPlayer 和性能问题
iOS:将 AVAudioPlayer 的实例从一个变量移动到另一个变量