SKAction playSoundFileNamed在500 mp3时失败了

在我的应用程序中,我需要使用很多不同的短mp3(大约500个项目一个接一个)

所以我使用SKAction playSoundFileNamed

在大约200声之后它崩溃了’无法加载资源 – 无法加载资源s234.mp3’。 记忆力增加到70mb。

怎么避免这个?

我尝试了什么:

  1. 在每次迭代中重新创建声音

    SKAction *mySound=[SKAction playSoundFileNamed:aa waitForCompletion:YES]; 
  2. 在.m的开头创建一个变量

     SKAction *mySound; 

并在迭代中重用它

  mySound=[SKAction playSoundFileNamed:aa waitForCompletion:YES]; 

2.在开始时将所有声音加载到arrays

 for (int j=0;j<500;j++){ NSString *aa=[NSString stringWithFormat:@"s%d.mp3", j]; [item.sounds addObject:[SKAction playSoundFileNamed:aa waitForCompletion:YES]]; } 

…但从未改变 – 它崩溃,无法加载MP3。

如何清理这个内存泄漏?

编辑我也试图关闭ARC并每次手动解除它。 没有改变。

这里的小曲子将允许您使用常规的旧SKAction,但在代码中自定义播放。

https://github.com/pepelkod/iOS-Examples/tree/master/PlaySoundWithVolume

 +(SKAction*)playSoundFileNamed:(NSString*)fileName atVolume:(CGFloat)volume waitForCompletion:(BOOL)wait{ // setup audio NSString* nameOnly = [fileName stringByDeletingPathExtension]; NSString* extension = [fileName pathExtension]; NSURL *soundPath = [[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:nameOnly ofType:extension]]; AVAudioPlayer *player = [[AVAudioPlayer alloc]initWithContentsOfURL:soundPath error:NULL]; [player setVolume:volume]; [player prepareToPlay]; SKAction* playAction = [SKAction runBlock:^{ [player play]; }]; if(wait == YES){ SKAction* waitAction = [SKAction waitForDuration:player.duration]; SKAction* groupActions = [SKAction group:@[playAction, waitAction]]; return groupActions; } return playAction; 

}

使用“适当的”声音引擎可能会更好。 您可以使用AVAudioPlayer甚至更好的ObjectAL (已包含在Kobold Kit中 )。 这样,您可以更好地控制预加载和缓存声音文件,并将流式音频(MP3)与短暂的声音效果(通常是CAF或WAV)区别对待。

对于非常短的声音文件,例如短于5秒,MP3并不理想。 你应该尝试使用CAF / WAV。

并考虑你的声音文件在内存中使用了多少。 假设每个mp3文件缓冲到250 KB缓冲区,时间为500,然后使用超过120 MB的内存。 不要看mp3文件的大小,因为它是一种压缩格式,很可能是未压缩缓冲的。

我想你的文件描述符已经用完了。 我发现每次运行playSoundFileNamed都会打开声音文件并且永远不会关闭…所以文件描述符不会被释放。

我在仪器上的测试让我相信大约有250个可用的文件描述符。 我的研究告诉我,不仅文件访问使用它们,还有其他东西。 所以我认为你的~200个声音文件听起来正好崩溃了。 每当声音文件是Xcode试图访问的下一个文件时,我从调试器中得不到任何东西,但是当下一个文件是png(我有更多的艺术然后是声音)时,它会给出,

错误= 24(打开的文件太多)

每次丢失时,我都会在玩游戏测试并从游戏场景切换回菜单场景时发现错误。 所以通常情况并不重要但是反复运行游戏场景的init方法会堆积这些打开的声音文件。

我搜索并搜索了一种关闭这些文件的方法,但却没有提出任何建议。 我正在考虑实现一个单例来运行我的声音并将所有的playSoundFileNamed调用移动到它中,这样它们只能被调用一次。 我认为这是Apple的一个错误。 这些文件应该用ARC关闭。 有没有人发现类似的东西?