使用 fileNamed 初始化 SKAudioNode 返回 nil

Posted

技术标签:

【中文标题】使用 fileNamed 初始化 SKAudioNode 返回 nil【英文标题】:Initializing SKAudioNode using fileNamed returns nil 【发布时间】:2016-04-09 15:16:52 【问题描述】:

这是我第一次使用 SKAudioNode。首先,我在 GameScene 类的顶部声明了一个属性:

var backgroundMusic: SKAudioNode!

现在我添加了一个辅助方法:

func playBackgroundMusic(name: String) 
    if backgroundMusic != nil 
        backgroundMusic.removeFromParent()
    

    backgroundMusic = SKAudioNode(fileNamed: name)
    backgroundMusic.autoplayLooped = true
    addChild(backgroundMusic)

现在我这样调用这个方法:

playBackgroundMusic("ABC.caf")

它在这一行抛出一个致命错误:

backgroundMusic.autoplayLooped = true

说:在展开可选值时意外发现 nil。

我确实确保了以下内容

ABC.caf 在我的项目中,并在复制包资源中列出。 拼写正确。

现在我还应该在哪里检查错误?

编辑:

这是我的配置信息:

Xcode 7.3 装有 ios 9.3.2 的 iPhone iOS 9.3 模拟器

设备和模拟器都不工作。

EDIT2:

我将代码更改为以下内容:

func playBackgroundMusic(name: String) 
    if backgroundMusic != nil 
        backgroundMusic.removeFromParent()
    

    let temp = SKAudioNode(fileNamed: name)
    temp.autoplayLooped = true
    backgroundMusic = temp
    //backgroundMusic = SKAudioNode(fileNamed: "SpaceGame.caf")
    //backgroundMusic.autoplayLooped = true
    addChild(backgroundMusic)

现在我的应用不再崩溃,但没有声音。有什么想法吗?

附:在我上次编辑该问题几分钟后,我尝试将该方法中的所有内容替换为:

runAction(SKAction.playSoundFileNamed(name, waitForCompletion: false))

还是没有声音。可能是声音文件有问题?

【问题讨论】:

您使用的是 Xcode 7.3 对吗? ***.com/q/36273271/3402095 对我来说,在使用 Xcode 7.1.1 时,即使我提供了错误的文件名,backgroundMusic 也不会以 nil 结尾,而是带有某种“空”SKAudioNode。不过,它不会崩溃。顺便问一下,您是否尝试过重新添加声音?你知道,从项目中删除它,然后转到 Product-> clean,然后再次将相同的声音拖到项目中并将其添加到 Copy Bundle Resources 部分......只是看看这是否与一些奇怪的缓存问题无关(但是我对此表示怀疑)。 @Whirlwind 是的,我在 Xcode 7.3 上。我试图删除音乐文件并将其重新添加回项目,并执行了清理。它仍然崩溃,因为它在展开可选时发现 nil。 您是否尝试使用“ABC”而不是“ABC.caf”? @GoodDoug 我试过了,同样的错误。 您是否检查以确保该文件包含在您的构建中?仅仅添加到项目中可能还不够好。另外,文件名区分大小写,您是否将文件命名为 SpaceGame.caf 而不是 spaceGame.caf 【参考方案1】:

我刚刚遇到了这个问题。显然,它现在只适用于局部变量。以下代码有效。

var background:SKAudioNode!

override func didMoveToView(view: SKView) 
    let bg = SKAudioNode(fileNamed: "bg.mp3")
    addChild(bg)
    background = bg

【讨论】:

非常好,+1,但为什么?【参考方案2】:

我用上面 EDIT2 中的代码解决了这个问题:

func playBackgroundMusic(name: String) 
    if backgroundMusic != nil 
        backgroundMusic.removeFromParent()
    

    let temp = SKAudioNode(fileNamed: name)
    temp.autoplayLooped = true
    backgroundMusic = temp
    //backgroundMusic = SKAudioNode(fileNamed: "SpaceGame.caf")
    //backgroundMusic.autoplayLooped = true
    //addChild(backgroundMusic)
    runAction(SKAction.playSoundFileNamed(name, waitForCompletion: false))

对于没有声音的部分,只需确保 iPhone 上的侧面开关不是红色即可。

【讨论】:

这值得一掌,既然你已经工作了,试着取出临时温度,看看它是否再次工作。我知道 SKAudioNode 的耳机插孔有问题,也许开关也有问题。【参考方案3】:

我遇到了与SKAudioNode(fileNamed:) 类似的问题,从自动完成和我遇到的问题来看,有两个具有相同参数签名的不同初始值设定项,一个返回SKAudioNode,一个返回SKNode 和我不知何故弄错了。我改用SKAudioNode(url:)(使用Bundle.main.url(forResource:withExtension:) 获取URL),一切都按预期工作。

【讨论】:

【参考方案4】:

已经有好几年了,但是我发现构造函数 SKAudioNode() 需要一些时间来加载声音——不管它有多大。即使是 50 kByte 的小声音文件也需要 0.25 秒才能加载。在初次使用之后,所有后续的声音加载只需要一小部分时间。 我猜 SpriteKit 会对应用文件中的所有声音进行一些缓存。

所以要解决第一个延迟声音的问题:像我在菜单中一样播放它们 - 零音量和零长度。

我的实验表明,在 Xcode 11 模拟器初始化时,预播放 20 个声音文件也需要 0.25 秒。所以我再次猜测预播放一个(!)声音会告诉 iOS 将所有声音文件预加载到内存中。

【讨论】:

以上是关于使用 fileNamed 初始化 SKAudioNode 返回 nil的主要内容,如果未能解决你的问题,请参考以下文章

调试为啥 SKScene init(fileNamed:) 返回 nil

Git的使用及网络编程多线程多进程

代理 模式

GIT命令学习

21.文件读写

js设计模式——1.代理模式