Ios SpriteKit SKAction runBlock:如何影响FPS性能?
我正在使用SKAction类别播放AVAudioPlayer声音-看起来如下:Ios SpriteKit SKAction runBlock:如何影响FPS性能?,ios,performance,sprite-kit,avaudioplayer,skaction,Ios,Performance,Sprite Kit,Avaudioplayer,Skaction,我正在使用SKAction类别播放AVAudioPlayer声音-看起来如下: + (SKAction *)atw_playSoundWithData:(NSData *)soundData { // If AVAudioSession is inactive do not make any sound if ([BAPAppDelegate isAudioSessionActive] == NO) { return [SKAction runBlock:^{}]
+ (SKAction *)atw_playSoundWithData:(NSData *)soundData {
// If AVAudioSession is inactive do not make any sound
if ([BAPAppDelegate isAudioSessionActive] == NO) {
return [SKAction runBlock:^{}];
} else {
// Create playSoundAction which starts on concurrent queue to gain speed
return [SKAction runBlock:^{
NSError *error;
AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithData:soundData error:&error];
if (!error) {
audioPlayer.numberOfLoops = 0;
[audioPlayer play];
// Cache audioPlayer to avoid autoreleasing before play end
[SKAction atw_cacheAudioPlayer:audioPlayer];
}
//NSLog(@"%s Added: %@ withError: %@, Cache: %lu", __PRETTY_FUNCTION__, audioPlayer, error, (unsigned long)[sATWAudioPlayersCache count]);
} queue:sATWAudioPlayersCacheQueue];
}
}
缓存AVAudioPlayer是为了避免过早释放玩家-方法如下:
static NSMutableSet *sATWAudioPlayersCache; // It's our cache
static dispatch_queue_t sATWAudioPlayersCacheQueue; // It's our concurrent queue of audioPlayers that are playing
+ (void)atw_cacheAudioPlayer:(AVAudioPlayer *)audioPlayer {
// Init cache for the first time
if (sATWAudioPlayersCache == nil) {
sATWAudioPlayersCache = [[NSMutableSet alloc] initWithCapacity:1];
sATWAudioPlayersCacheQueue = dispatch_queue_create("com.AppThatWorks.SKAction+ATWSound.sATWAudioPlayersCacheQueue", DISPATCH_QUEUE_CONCURRENT);
}
if (audioPlayer == nil) return;
dispatch_barrier_async(sATWAudioPlayersCacheQueue, ^{
[sATWAudioPlayersCache addObject:audioPlayer];
});
// Set delayed cache clear event for that audioPlayer (with barrier also to ensure exclusive access)
double delay = [audioPlayer duration]+0.1; // +0.1 second buffer for safe sound end
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC));
dispatch_after(popTime, sATWAudioPlayersCacheQueue, ^(void){
dispatch_barrier_async(sATWAudioPlayersCacheQueue, ^{
// For safety sake, stop audioPlayer to avoid potential bad access while removing/autoreleasing.
// It could happen if delay was nearly equal to [audioPlayer duration] (i.e. released while stopping).
[audioPlayer stop];
[sATWAudioPlayersCache removeObject:audioPlayer];
//NSLog(@"%s Removed: %@ , Cache: %lu", __PRETTY_FUNCTION__, audioPlayer, (unsigned long)[sATWAudioPlayersCache count]);
});
});
}
我发现,以这种方式播放大约每秒10次的声音会影响每秒60到49次的FPS(不幸的是,它非常明显),尽管CPU的利用率仍然保持在20%。因为跳过播放声音会修复FPS性能,所以我的问题来自:
问题:SKAction runBlock:如何影响FPS?(或者我的GCD解决方案/AVAudioPlayer如何做到这一点?您是否尝试过不使用dispatch async?在任何情况下,通过使用“适当的”openal音频引擎,特别是objectal@LearnCocos2D使用正确的音频引擎是完全正确的。我对反对者的建议是不够的;它将为您节省大量时间,非常易于使用,性能卓越。Thx!我会尝试一下,但如果不理解这一点,我就不愿意改变它:为什么CPU在玩游戏时会感到无聊,而FPS会受到影响(以及AVAudioPlayer与之有什么关系)。更改为串行队列减轻了痛苦,尽管我不太明白。fps是平均值,cpu%也很可能是平均值。所以,如果一个帧占用100%,但接下来的10个帧不占用相对较好的fps或CPU%时,性能仍然很差吗。如果你想要精确的计时,使用仪器。