Swift Spritekit:不播放背景音乐

Swift Spritekit:不播放背景音乐,swift,background,sprite-kit,Swift,Background,Sprite Kit,我有两个场景,我希望背景音乐都能播放。问题是音乐只在应用程序第一次打开时播放。如果我按下按钮转到第二个场景,音乐会在场景过渡时播放,但在过渡结束时停止。第二个场景没有音乐,如果我回到第一个场景,那里也没有音乐。 音乐总是在场景之间的过渡期间播放(这就是为什么我使用了很长的过渡时间,只是为了确认(我不知道为什么) 我认为它不会播放的原因是,一旦场景发生变化,音频节点将被释放。我不确定为什么它只在过渡期间播放。我也从未使用过音频节点,但我创建了自己的自定义类来处理所有音频 let audio = J

我有两个场景,我希望背景音乐都能播放。问题是音乐只在应用程序第一次打开时播放。如果我按下按钮转到第二个场景,音乐会在场景过渡时播放,但在过渡结束时停止。第二个场景没有音乐,如果我回到第一个场景,那里也没有音乐。 音乐总是在场景之间的过渡期间播放(这就是为什么我使用了很长的过渡时间,只是为了确认(我不知道为什么)


我认为它不会播放的原因是,一旦场景发生变化,音频节点将被释放。我不确定为什么它只在过渡期间播放。我也从未使用过音频节点,但我创建了自己的自定义类来处理所有音频

let audio = JKAudioPlayer.sharedInstance()
另外,我不会复制和粘贴代码。当您可以只使用一个类来处理音频时,两个场景中的代码都是相同的。下面是一个使用我创建的名为JKAudioPlayer的自定义类的解决方案。只需创建一个新的Swift类并将代码粘贴到其中。因为稍后声明的音频对象不是场景的一部分,所以它将继续/允许当你过渡时,你可以玩ic

import Foundation
import SpriteKit
import AVFoundation
import AVFoundation.AVAudioSession

/**Manages a shared instance of JKAudioPlayer.*/
private let JKAudioInstance = JKAudioPlayer()

/**Provides an easy way to play sounds and music. Use sharedInstance method to access a single object for the entire game to manage the sound and music.*/
public class JKAudioPlayer {

    /**Used to access music.*/
    var musicPlayer: AVAudioPlayer!

    /** Allows the audio to be shared with other music (such as music being played from your music app). If this setting is false, music you play from your music player will stop when this app's music starts. Default set by Apple is false. */
    static var canShareAudio = false {
        didSet {
            canShareAudio ? try! AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient) : try! AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategorySoloAmbient)
        }
    }

    /**Creates an instance of the JAAudio class so the user doesn't have to make their own instance and allows use of the functions. */
    public class func sharedInstance() -> JKAudioPlayer {
        return JKAudioInstance
    }

/**Plays music. You can ignore the "type" property if you include the full name with extension in the "filename" property. Set "canShareAudio" to true if you want other music to be able to play at the same time (default by Apple is false).*/
    public func playMusic(fileName: String, withExtension type: String = "") {
        if let url = NSBundle.mainBundle().URLForResource(fileName, withExtension: type) {
            musicPlayer = try? AVAudioPlayer(contentsOfURL: url)
            musicPlayer.numberOfLoops = -1
            musicPlayer.prepareToPlay()
            musicPlayer.play()
        }
    }

    /**Stops the music. Use the "resumeMusic" method to turn it back on. */
    public func stopMusic() {
        if musicPlayer != nil && musicPlayer!.playing {
            musicPlayer.currentTime = 0
            musicPlayer.stop()
        }
    }

    /**Pauses the music. Use the "resumeMusic" method to turn it back on. */
    public func pauseMusic() {
        if musicPlayer != nil && musicPlayer!.playing {
            musicPlayer.pause()
        }
    }

    /**Resumes the music after being stopped or paused. */
    public func resumeMusic() {
        if musicPlayer != nil && !musicPlayer!.playing {
            musicPlayer.play()
        }
    }

    /**Plays a sound only once. Must be used inside a runAction(...) method.*/
    public func playSound(fileName: String) -> SKAction? {
        return SKAction.playSoundFileNamed(fileName, waitForCompletion: false)
    }
}
要使用它,请创建一个可以访问音频的全局变量

let audio = JKAudioPlayer.sharedInstance()
然后,当您想要播放音乐时,您可以在scene类的didMoveToView函数中轻松调用它

audio.playMusic("MusicName")
您还可以通过调用暂停/停止/恢复音乐功能来控制它,如下所示:

audio.stopMusic()
如果您希望用户能够在后台播放自己的音乐,例如从他们的iTunes库播放音乐,而无需应用程序暂停他们的音乐,那么您可以在GameViewController的viewDidLoad函数中将canShareAudio设置为true

audio.canShareAudio = true

这是Swift 3测试和运行的代码,您需要将文件的扩展名放在末尾,否则无法定位声音文件

在新的Swift文件中复制并粘贴

import Foundation
import SpriteKit
import AVFoundation

    public let audio = JKAudioPlayer.sharedInstance()


    private let JKAudioInstance = JKAudioPlayer()


    public class JKAudioPlayer {


    var musicPlayer: AVAudioPlayer!


    static var canShareAudio = false {
        didSet {
        canShareAudio ? try! AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryAmbient) : try! AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategorySoloAmbient)
        }
    }

    public class func sharedInstance() -> JKAudioPlayer {
        return JKAudioInstance
    }
    public func playMusic(fileName: String, withExtension type: String = "") {
        if let url = Bundle.main.url(forResource: fileName, withExtension: type) {
            musicPlayer = try? AVAudioPlayer(contentsOf: url)
            musicPlayer.numberOfLoops = -1
            musicPlayer.prepareToPlay()
            musicPlayer.play()
        }
    }


    public func stopMusic() {
        if musicPlayer != nil && musicPlayer!.isPlaying {
            musicPlayer.currentTime = 0
            musicPlayer.stop()
        }
    }


    public func pauseMusic() {
        if musicPlayer != nil && musicPlayer!.isPlaying {
            musicPlayer.pause()
        }
    }

    public func resumeMusic() {
        if musicPlayer != nil && !musicPlayer!.isPlaying {
            musicPlayer.play()
        }
    }

    public func playSound(fileName: String) -> SKAction? {
        return SKAction.playSoundFileNamed(fileName, waitForCompletion: false)
    }
}
要播放任何文件,只需输入

audio.playMusic(fileName: "NameOfFile")
要停止音乐,只需把它放在需要停止的地方

audio.stopMusic()

你说它只在应用程序第一次打开时播放,但你说它只在过渡期间播放。或者你是说它在应用程序第一次打开时播放,并在过渡期间继续播放?还是像你稍后所说的,在返回场景1和场景2时也在过渡期间播放?而且,你似乎在两个场景中都有相同的音频代码。你知道吗可能需要构建一个类来处理音频,这样您就不必保留复制和粘贴代码。例如,我构建了一个名为jkadioplayer的类,它可以为我处理所有音频,每当我需要它时,我就在特定场景中调用它:audio.playMusic(“Music”)。非常感谢您的帮助。您的解决方案非常完美!如果您真的声明您将我的答案更新为Swift 3,将不胜感激,因为这是我的答案的副本。
audio.stopMusic()