播放非常短的声音(约0.5秒)会在Swift中编写的SpriteKit iOS游戏中产生打嗝(如滞后)。在其他问题中,我读到我应该prepareToPlay()
声音,我做了。
我甚至使用变量(soundReady
)来检查声音是否在播放前准备好了。我也会在完成播放后重新准备声音(audioPlayerDidFinishPlaying()
)。以下是代码的相关部分:
class GameScene: SKScene, AVAudioPlayerDelegate {
var splashSound = NSURL()
var audioPlayer = AVAudioPlayer()
var soundReady = false
override func didMoveToView(view: SKView) {
let path = NSBundle.mainBundle().pathForResource("plopSound", ofType: "m4a")
splashSound = NSURL(fileURLWithPath: path)
audioPlayer = AVAudioPlayer(contentsOfURL: splashSound, error: nil)
audioPlayer.delegate = self
soundReady = audioPlayer.prepareToPlay()
}
func playSound(){
if(soundReady){
audioPlayer.play()
soundReady = false
}
}
func audioPlayerDidFinishPlaying(player: AVAudioPlayer!, successfully flag: Bool){
//Prepare to play after Sound finished playing
soundReady = audioPlayer.prepareToPlay()
}
}
我不知道我在哪里出错了。我觉得我已经尝试了所有东西(包括但不限于:只准备一次,在播放后立即准备,不使用变量,而只是prepareToPlay())。
其他信息:
答案 0 :(得分:15)
我遇到了同样的问题并在backgroundQueue中播放了声音。
这是一个很好的例子:https://stackoverflow.com/a/25070476/586204。
let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
audioPlayer.play()
})
答案 1 :(得分:7)
只需从@brilliantairic添加Swift 3版本的解决方案。
steps
答案 2 :(得分:0)
当我多次打游戏时,会导致访问不畅。我认为玩家正在被释放,因为这不是线程安全的。我创建了一个串行队列来缓解此问题。
class SoundManager {
static let shared = SoundManager()
private init() {
try? AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try? AVAudioSession.sharedInstance().setActive(true)
}
private let serialQueue = DispatchQueue(label: "SoundQueue", qos: .userInitiated)
private var player: AVAudioPlayer?
static func play(_ sound: Sound) {
shared.play(sound)
}
func play(_ sound: Sound) {
guard let url = Bundle.main.url(forResource: sound.fileName, withExtension: "mp3")
else { return }
do {
try serialQueue.sync {
self.player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileTypeMPEGLayer3)
DispatchQueue.main.async {
self.player?.play()
}
}
} catch let error as NSError {
print("error: \(error.localizedDescription)")
}
}
}