在Spritekit中添加音效

3

我正在制作一个类似Flappy Bird的游戏,我想为收集到硬币时添加声音效果。这是我的代码:

import SpriteKit
import AVFoundation

class GameScene: SKScene {

    var coinSound = NSURL(fileURLWithPath:NSBundle.mainBundle().pathForResource("Super Mario Bros.- Coin Sound Effect", ofType: "mp3")!)
    var audioPlayer = AVAudioPlayer()

在我的didMoveToView方法中:

audioPlayer = AVAudioPlayer(contentsOfURL: coinSound, error: nil)
audioPlayer.prepareToPlay()

针对第二部分(在我的didMoveToView中),第一行一直显示错误:

调用可能会抛出异常,但没有标记为“try”,也没有处理错误

我该如何修复此问题?


1
请查看此帖子:https://dev59.com/QWAf5IYBdhLWcg3wqUSN - JanR
当答案被更正后,这个程序会真的播放声音吗? - Confused
我知道你已经标记了一个答案,但实际上我会使用SKAction.playSound...来播放短暂的一次性声音。AVFoundation更适合用于背景音乐。 - crashoverride777
3个回答

15

我知道你已经选择了一个答案,但是如果你重新阅读这个问题或者给未来的读者看,使用SKActions来播放一次短暂的声音会更容易。

AVFoundation更适合用于背景音乐。

例如:

class GameScene: SKScene {

     // add as class property so sound is preloaded and always ready
     let coinSound = SKAction.playSoundFileNamed("NAMEOFSOUNDFILE", waitForCompletion: false)
}

然后当您需要播放声音时,只需说这句话

run(coinSound)

希望这可以帮到你


我现在正在使用这种方式。它简单得多,如果动作已经预先创建,似乎会缓存音频文件,因此第一次播放时没有加载/延迟。 - Confused
是的,我没有意识到这是一个七个月前的问题,以为它是新的。 - crashoverride777

2
audioPlayer = AVAudioPlayer(contentsOfURL: coinSound, error: nil)

在Swift中不再使用这种方式处理错误。您必须使用do-try-catch语法。

do {
    audioPlayer = try AVAudioPlayer(contentsOfURL: coinSound)
    audioPlayer.prepareToPlay()
}
catch let error {
    // handle error
}

或者,如果您不想编写任何错误处理代码,可以将您的audioPlayer变量设置为可选,并编写一个可失败的try?

audioPlayer = try? AVAudioPlayer(contentsOfURL: coinSound)
audioPlayer?.prepareToPlay()

这更接近于您尝试的代码,其中您将nil作为错误参数传递。
或者,如果在出现错误时崩溃是适当的行为,则可以采用以下方法:
guard let audioPlayer = try? AVAudioPlayer(contentsOfURL: coinSound) else {
    fatalError("Failed to initialize the audio player with asset: \(coinSound)")
}
audioPlayer.prepareToPlay()
self.audioPlayer = audioPlayer

如果您有时间并且愿意,能否在下面的Swift 3版本中回答我的评论中的问题? - Confused
一个避免立即崩溃的替代方法是 let audioPlayer = try! etc...。虽然你无法获得详细的错误信息,但如果你正在调试,Xcode 会定位到具体位置。 - Andrew Duncan

0

Swift 3.0+

针对@nhgrif提供的上述guard let示例,这里是Swift 3.0+的实现方式:

var coinSound = NSURL(fileURLWithPath:Bundle.main.path(forResource: "Super Mario Bros.- Coin Sound Effect", ofType: "mp3")!)
var audioPlayer = AVAudioPlayer()

func playCoinSound(){
    guard let soundToPlay = try? AVAudioPlayer(contentsOf: coinSound as URL) else {
        fatalError("Failed to initialize the audio player with asset: \(coinSound)")
    }
    soundToPlay.prepareToPlay()

//  soundToPlay.play() // NO IDEA WHY THIS DOES NOT WORK!!!???

    self.audioPlayer = soundToPlay
    self.audioPlayer.play() // But this does work... please let me know why???
}

playCoinSound()

我不知道。我只是从我(越来越庞大的)参考文件中复制了所有其他警卫的内容。这是来自nhgrif的答案。直到今天,我才开始使用它,然后发现了swift 3的更改,并对需要重复自己以使其播放感到好奇。 - Confused
很酷,只是在问而已。在这种情况下最好使用返回并优雅地退出,以避免应用程序崩溃。 - crashoverride777

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接