我创建了一个SCNNode
的子类。它由几个子节点组成。
我声明了一个方法,即soundCasual()
,它向此类的实例添加了一个SCNAudioPlayer
。当调用此方法时,一切都按预期工作,并且正在播放音频。每当点击该节点(手势)时,此方法将在该节点上调用。
代码:
class MyNode: SCNNode {
let wrapperNode = SCNNode()
let audioSource5 = SCNAudioSource(fileNamed: "audiofile.mp3")
override init() {
super.init()
if let virtualScene = SCNScene(named: "MyNode.scn", inDirectory: "Assets.scnassets/Shapes/MyNode") {
for child in virtualScene.rootNode.childNodes {
wrapperNode.addChildNode(child)
}
}
}
func soundCasual() {
DispatchQueue.global(qos: .userInteractive).async { [weak self] in
if let audioSource = self?.audioSource5 {
let audioPlayer = SCNAudioPlayer(source: audioSource)
self?.wrapperNode.removeAllAudioPlayers()
self?.wrapperNode.addAudioPlayer(audioPlayer)
}
}
}
}
仪器问题(分配)
当我分析整个代码库(其中还有其他内容)时,我发现每当我点击该节点时,在Instruments中进行分析时,SCNAudioPlayer的分配计数会增加一次。但所有增长都是持久性的。根据SCNAudioPlayer
的定义,我认为播放器在播放后被移除,因此增量应该在瞬态分配中,但它并不像这样工作。这就是为什么我在向节点添加SCNAudioPlayer之前尝试了removeAllAudioPlayers()
,如soundCasual()
的代码所示。但问题仍然存在。
在拍摄此快照时,我大约点击了该节点17次,并且对于SCNAudioPlayer的Persistent分配,它也显示为17。
注意: SCNAudioSource
为10,这是正确的,因为我在应用程序中使用了10个音频源
我的应用程序中所有其他SCNNodes都出现了这种情况。请帮忙,因为我无法理解我到底错过了什么。
编辑
按建议,我将我的init()
更改为
let path = Bundle.main.path(forResource: "Keemo", ofType: "scn", inDirectory: "Assets.scnassets/Shapes/Keemo")
if let path = path , let keemo = SCNReferenceNode(url: URL(fileURLWithPath: path)) {
keemo.load()
}
func soundPlay() {
DispatchQueue.global(qos: .userInteractive).async { [weak self] in
if let audioSource = self?.audioSourcePlay {
audioSource.volume = 0.1
let audioPlayer = SCNAudioPlayer(source: audioSource)
self?.removeAllAudioPlayers()
self?.addAudioPlayer(audioPlayer)
}
}
}
尽管在Instruments中分配的资源表明audioPlayers是持久的,但是检查node.audioPlayers
后显示在某一时刻只有一个audioPlayer节点被连接。
编辑
即使在使用XCode默认创建的Scenekit应用程序中附带的样板代码中,这个问题也会出现。因此,这个问题已经被提升为苹果公司的一个错误。 https://bugreport.apple.com/web/?problemID=43482539
解决方法
我使用AVAudioPlayer代替SCNAudioPlayer,虽然不完全相同,但至少这种方式不会导致内存崩溃。
.audioPlayers
的输出是什么? - Stephen Furlani