touchesMoved 中的 SpriteKit + AVAudioPlayer:杀死 fps
SpriteKit + AVAudioPlayer in touchesMoved: kills fps
在 SpriteKit 应用程序中,当用户在屏幕上移动一个块时,我会播放点击声音,但这会导致严重的滞后(fps 下降到接近零)。
代码:
• self.audioPlayers
是一个强大的 NSMutableArray,它保存当前正在播放的 AVAudioPlayer
s 并在调用 audioPlayerDidFinishPlaying:
委托方法时删除它们。
• blockShouldMove
方法将触摸位置与其之前的位置进行比较,如果用户将光标移动了足够的距离,则只有 returns YES,因此我们最多只能同时播放大约 8 个声音。
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *oneTouch = [touches anyObject];
CGPoint location = [oneTouch locationInNode:self];
if (![self blockShouldMove:location]) {
return;
}
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:@"click_01.mp3" ofType:nil];
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:soundFilePath] error:nil];
[audioPlayer prepareToPlay];
audioPlayer.volume = 1.0;
audioPlayer.numberOfLoops = 0;
audioPlayer.delegate = self;
[audioPlayer play];
[self.audioPlayers addObject:audioPlayer];
}
在模拟器和真实设备(iOS 和 tvOS)上,如果我用手指画圈,fps 几乎下降到零,直到我松开手指。
如果我删除整个 AVAudioPlayer
并使用 [SKAction playSoundFileNamed:@"click_01.mp3" waitForCompletion:NO]
,一切正常。但不幸的是,SKAction
声音处理对我来说很糟糕,因为无法设置音量。
有什么办法可以使它变得更好吗?
这是一种间接的“回答”,更多的是评论,但以这种形式写出来太长了。
我 运行 遇到了类似 SpriteKit 游戏的问题。我通过删除 AVAudioPlayer
s 并使用场景的音频引擎解决了这个问题。我将一堆 AVAudioPlayerNode
连接到主混音器节点并开始播放(无)。每当我想要某种声音效果时,我都会抓住下一个音频播放器节点(循环方式,并且有足够的节点以便我确定它会空闲)并为其安排一个预加载的声音缓冲区.
要点是,对于 SpriteKit 中更复杂的音频,您可能需要通过音频引擎并构建适合您想要执行的操作的声音图。多个 AVAudioPlayer
同时存在似乎以某种方式相互踩踏并导致延迟。
但是,如果您还没有尝试过 SKAudioNode
功能,我建议您先尝试一下。您应该能够 运行 在音频节点上执行一个操作来调节音量。我没有走那条路,因为我无法让立体声声像按照我想要的方式工作。如果这对你想做的事情有效,它可能比设置你自己的声音图更简单。
如果想看我最终使用的方案,可以看https://github.com/bg2b/RockRats/blob/master/Asteroids/Sounds.swift
在 SpriteKit 应用程序中,当用户在屏幕上移动一个块时,我会播放点击声音,但这会导致严重的滞后(fps 下降到接近零)。
代码:
• self.audioPlayers
是一个强大的 NSMutableArray,它保存当前正在播放的 AVAudioPlayer
s 并在调用 audioPlayerDidFinishPlaying:
委托方法时删除它们。
• blockShouldMove
方法将触摸位置与其之前的位置进行比较,如果用户将光标移动了足够的距离,则只有 returns YES,因此我们最多只能同时播放大约 8 个声音。
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *oneTouch = [touches anyObject];
CGPoint location = [oneTouch locationInNode:self];
if (![self blockShouldMove:location]) {
return;
}
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:@"click_01.mp3" ofType:nil];
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:soundFilePath] error:nil];
[audioPlayer prepareToPlay];
audioPlayer.volume = 1.0;
audioPlayer.numberOfLoops = 0;
audioPlayer.delegate = self;
[audioPlayer play];
[self.audioPlayers addObject:audioPlayer];
}
在模拟器和真实设备(iOS 和 tvOS)上,如果我用手指画圈,fps 几乎下降到零,直到我松开手指。
如果我删除整个 AVAudioPlayer
并使用 [SKAction playSoundFileNamed:@"click_01.mp3" waitForCompletion:NO]
,一切正常。但不幸的是,SKAction
声音处理对我来说很糟糕,因为无法设置音量。
有什么办法可以使它变得更好吗?
这是一种间接的“回答”,更多的是评论,但以这种形式写出来太长了。
我 运行 遇到了类似 SpriteKit 游戏的问题。我通过删除 AVAudioPlayer
s 并使用场景的音频引擎解决了这个问题。我将一堆 AVAudioPlayerNode
连接到主混音器节点并开始播放(无)。每当我想要某种声音效果时,我都会抓住下一个音频播放器节点(循环方式,并且有足够的节点以便我确定它会空闲)并为其安排一个预加载的声音缓冲区.
要点是,对于 SpriteKit 中更复杂的音频,您可能需要通过音频引擎并构建适合您想要执行的操作的声音图。多个 AVAudioPlayer
同时存在似乎以某种方式相互踩踏并导致延迟。
但是,如果您还没有尝试过 SKAudioNode
功能,我建议您先尝试一下。您应该能够 运行 在音频节点上执行一个操作来调节音量。我没有走那条路,因为我无法让立体声声像按照我想要的方式工作。如果这对你想做的事情有效,它可能比设置你自己的声音图更简单。
如果想看我最终使用的方案,可以看https://github.com/bg2b/RockRats/blob/master/Asteroids/Sounds.swift