Ios SpriteKit SKAction runBlock:如何影响FPS性能?

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类别播放AVAudioPlayer声音-看起来如下:

+ (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%时,性能仍然很差吗。如果你想要精确的计时,使用仪器。