致命的音效
音效是游戲的一個(gè)重要元素怕午。SpriteKit對(duì)音效也提供了支持。
在SpriteKit中有2種方式來(lái)播放音效:
- 使用SKAudioNode:
audioNode = SKAudioNode(fileNamed: filename)
audioNode!.autoplayLooped = false
self.addChild(audioNode!)
audioNode!.runAction(SKAction.play())
2.使用SKAction.playSoundFileNamed:
let soundAction = SKAction.playSoundFileNamed("\(towerType.rawValue)Fire.mp3", waitForCompletion: false)
這是Apple官方推薦的方法堡距,幾乎所有的SpriteKit教程也都是用的這2種方式。
如果你像我一樣吏颖,在游戲中有很多音效需要不斷播放的話,你會(huì)面臨兩個(gè)問(wèn)題:
1.在多個(gè)音效一起播放的時(shí)候疚俱,你偶然會(huì)遇到一個(gè)uncaught exception
*** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'required condition is false: _engine->IsRunning()'
2.反復(fù)播放后你會(huì)發(fā)現(xiàn)內(nèi)存只增不減缩多。
這兩個(gè)問(wèn)題都會(huì)造成應(yīng)用崩潰。第一種是偶然性的崩潰衬吆,第二種是累積性的崩潰。
所以我說(shuō)姆泻,這是致命的音效冒嫡。
觀察到這個(gè)現(xiàn)象后,這個(gè)問(wèn)題困擾我2個(gè)星期的時(shí)間孝凌。查了各種資料。
有人用延遲了解決第一個(gè)問(wèn)題瓣赂。
比如:
https://forums.developer.apple.com/thread/27980
但是效果并不完美片拍。
解決方法
經(jīng)過(guò)探索我終于意識(shí)到,SpriteKit的音效播放本身存在問(wèn)題捌省。
只有徹底放棄它才可以使問(wèn)題得到解決。
經(jīng)過(guò)驗(yàn)證方面,以下2種方式都可以成功:
方法一:AudioServicesPlaySystemSound
var dict = [String:SystemSoundID]()
func play(fileName:String){
if let soundId = dict[fileName] {
AudioServicesPlaySystemSound(soundId)
} else if let soundURL = NSBundle.mainBundle().URLForResource(fileName, withExtension: "mp3") {
var mySound: SystemSoundID = 0
AudioServicesCreateSystemSoundID(soundURL, &mySound)
dict[fileName] = mySound
AudioServicesPlaySystemSound(mySound)
}
}
方法二:AVAudioPlayer
var dict2 = [String:AVAudioPlayer]()
func play(fileName:String){
if let player = dict2[fileName] {
player.play()
} else{
let path = NSBundle.mainBundle().pathForResource(fileName, ofType:"mp3")!
let url = NSURL(fileURLWithPath: path)
do {
let sound = try AVAudioPlayer(contentsOfURL: url)
//player = sound
dict2[fileName] = sound
sound.playAtTime(0)
} catch {
// couldn't load file :(
}
}
}
注意色徘,在我的游戲中,幾個(gè)聲音文件(.mp3)反復(fù)播放横腿,所以我將它們放在Dictionary中,避免每次都要加載耿焊。
使用后,崩潰沒(méi)了器腋,內(nèi)存的使用也終于正常了钩杰。