touchesMoved中的SpriteKit + AVAudioPlayer:杀死fps

Posted

技术标签:

【中文标题】touchesMoved中的SpriteKit + AVAudioPlayer:杀死fps【英文标题】:SpriteKit + AVAudioPlayer in touchesMoved: kills fps 【发布时间】:2020-12-28 13:34:59 【问题描述】:

在 SpriteKit 应用程序中,当用户在屏幕上移动一个块时,我会播放点击声音,但这会导致严重的延迟(fps 下降到接近于零)。

代码:

self.audioPlayers 是一个强大的 NSMutableArray,它保存当前正在播放的 AVAudioPlayers,并在调用 audioPlayerDidFinishPlaying: 委托方法时将其删除。

blockShouldMove 方法将触摸位置与其之前的位置进行比较,并且仅在用户将光标移动足够距离时才返回 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 的声音处理对我来说很糟糕,因为无法设置音量。

有什么可以做的更好的吗?

【问题讨论】:

【参考方案1】:

这是一种间接的“答案”,更像是一种评论,但以这种形式写出来太长了。

我在使用 SpriteKit 游戏时遇到了类似的问题。我通过删除AVAudioPlayers 并使用场景的音频引擎解决了这个问题。我将一堆AVAudioPlayerNodes 连接到主混音器节点并开始播放(什么都没有)。每当我想要某种声音效果时,我都会抓取下一个音频播放器节点(循环方式,并且它们足够多,因此我确信它会空闲)并为其安排一个预加载的声音缓冲区.

关键是,对于 SpriteKit 中更复杂的音频,您可能需要通过音频引擎并构建适合您想要执行的操作的声音图。同时存在的多个AVAudioPlayers 似乎以某种方式相互踩踏并导致延迟。

但是,如果您还没有尝试过 SKAudioNode 功能,我建议您先尝试一下。您应该能够在音频节点上运行操作来调整音量。我没有走那条路,因为我无法让立体声声像以我想要的方式工作。如果这适用于您想要做的事情,它可能比设置您自己的声音图更简单。

如果想看我最终使用的解决方案,可以看https://github.com/bg2b/RockRats/blob/master/Asteroids/Sounds.swift

【讨论】:

以上是关于touchesMoved中的SpriteKit + AVAudioPlayer:杀死fps的主要内容,如果未能解决你的问题,请参考以下文章

SpriteKit touchesMoved 在 SKSpritenode 的子类中使用时不稳定

如何在 SpriteKit 中呈现场景后立即接收触摸事件?

SpriteKit:如何检测从节点外部开始的节点上的触摸

在滚动视图中的自定义视图中使用触摸进行缩放。 touchesMoved 未调用

使用 TouchesMoved 跟踪两个手指

UIScrollview touchesbegin,touchesmoved,touchesendactions