botp
November 17, 2025, 8:17am
1
在iOS启动游戏后一段时间,开始出现这样的报错(启动了Enable API Error Logging):
[FMOD] ChannelControl::isPlaying(0x171e366af:false) returned ERR_CHANNEL_STOLEN for CHANNELCONTROL (0xE40045).
[FMOD] ChannelControl::stop() returned ERR_CHANNEL_STOLEN for CHANNELCONTROL (0xE40045).
这些日志断断续续出现,但这时游戏还没有明显的问题。
但游戏继续游玩一段时间后,会出现一个明显的卡顿,然后所有音频都会停止。之后似乎所有音频都会触发上述的报错,日志里全是这类报错。看起来像是Channel用完了。配置里的Virtual Channel Count是128,Real Channel Count是32。
这个问题出现后,如果将游戏切到后台,声音会突然恢复播放。之后再切回前台就不会再有上述报错了。
顺便一说,声音停止后不久会出现这样的Warning:
[FMOD] EventInstance::update : Event {8fa27686-8af5-47f3-87a5-6ddc49a86dfa} waited 52 milliseconds for sample data to load. Preload sample data to avoid this delay.
这种Warning只会出现一两条,似乎是由声音停止后最先尝试播放的事件发出的警告,之后便不再出现。但前面提到的两种报错会不停出现,刷出一大堆,直到切后台使其恢复或者关闭游戏。
这个问题是我们将游戏从Unity2020升级到Unity2022后发现的,使用的FMOD版本是2.02.04。同一个项目打包的安卓项目没有出现这种情况,只有iOS出现了。
li_fmod
November 18, 2025, 11:00pm
2
你好,
感谢你提供的详细信息!
这个错误通常表示:原来的声道已经被系统回收或复用了,你当前操作的 Channel 句柄已经不再指向那个声音。
在正常情况下,少量的 ERR_CHANNEL_STOLEN 是正常现象(声道复用导致)。但像你描述的这种数量非常多,声音全部都不响的情况,听起来更像是Mixer 在运行过程中意外进入了暂停(mixer suspend)状态,但没有被正确 resume。
当 mixer 不再混音时,旧声道会全部被判定为失效,因此会持续返回 ERR_CHANNEL_STOLEN。
这一点听起来也非常符合 mixer 被暂停的情况:
切到后台后, Unity / iOS 会触发一次 AudioSession suspend/resume → FMOD mixer 会被重新初始化 → 声音恢复正常。
这条警告只是再说某个声音在等待加载样本数据,它一般不会导致整个声音系统中断,通常是在声音已经停止后,第一个尝试播放的事件触发的警告。
Unity 2022 对 iOS 的音频策略(AudioSession)确实有一些改变,有可能导致旧版FMOD 在遇到某些session切换时mixer被暂停但没有正确恢复,不知你们是否尝试过升级到最新的FMOD 2.02版本后,看看是否还有这种现象出现呢?
还有就是如果Logging Level设置的是Log等级的话,能否麻烦查查看日志在出现你所描述这些问题之前,哪怕没有手动切换app到后台,是否还是有意外触发类似 System::mixerSuspend 这样的记录呢?
botp
November 19, 2025, 3:14am
3
感谢你的回复!
根据你的回复,我又进行了一些调试。我试着在游戏中手动调用mixerSuspend(),发现表现看起来确实和我遇到的问题很像。
我试着将LogLevel设置为Log,手动调用mixerSuspend后可以看到日志。
[FMOD] SystemI::mixerSuspend : Suspending output.
但在iOS端真机触发了静音问题后,并没有这样的日志(我确定真机上其他的FMOD的Log级日志已经打出来了)。并且在触发了静音问题后,我直接调用mixerResume()是无效的,依旧没有声音。我必须先调用mixerSuspend(),再调用mixerResume(),才能够回复声音的播放。
目前还是不清楚具体的原因。请问有拿到Mixer当前是不是suspend状态之类的API吗?有没有什么办法确认Mixer当前是否在正常工作?如果能确认问题发生了的话,至少我可以在出现问题后手动resume一下。
再次感谢你的帮助。
botp
November 19, 2025, 12:05pm
4
我又发现了一些线索,这似乎和低内存的情况有关。
许多iOS机型的内存都比较小,较容易触发因内存占用过高而闪退的情况。我利用Application.lowMemory监听内存过低的警告,然后发现出现静音问题前,总是会有警告日志。之后我通过分配长度5000000的int值List来模拟内存消耗,成功在游戏基本处于待机的状态下复现了两次静音。这种方式不是很稳定,有时候可能闪退比静音先到来。但反复尝试这个方案后发现确实能够复现。并且和之前出现静音时的情况较为符合(都是内存占用较大的时候出现的)。
这可能也是为什么同样是iOS设备,有些设备更容易复现,有些更难复现的原因。内存低的设备更容易复现该问题。
同时,反复测试后我发现这并不是一个Unity 2022引入的问题,我使用2020时期的包体也复现了这个问题。通过进入一些占用内存较高的关卡,并在过高导致闪退前关闭关卡。只是2020似乎更难复现一点(存疑)?反复挑战内存阈值数次以后才成功复现了出来。
以上内容均为多次测试后的猜测,未必准确。(不过Unity 2020也复现了静音是一个好消息,至少我们不用因为这个问题拖延升级到Unity 2022的上线时间了。)
只是不知道这个问题FMOD这边是不是可以做些什么?或者,我有没有办法获取FMOD当前音频是否能够正常播放之类的状态的方法?这样的话我至少可以在某些时间点尝试检测一下有没有发生该问题。
li_fmod
November 20, 2025, 4:20am
5
感谢你持续进行的测试和补充的详细信息!
botp:
但在iOS端真机触发了静音问题后,并没有这样的日志(我确定真机上其他的FMOD的Log级日志已经打出来了)。并且在触发了静音问题后,我直接调用mixerResume()是无效的,依旧没有声音。我必须先调用mixerSuspend(),再调用mixerResume(),才能够回复声音的播放。
目前还是不清楚具体的原因。请问有拿到Mixer当前是不是suspend状态之类的API吗?有没有什么办法确认Mixer当前是否在正常工作?如果能确认问题发生了的话,至少我可以在出现问题后手动resume一下。
很遗憾,据我所知,FMOD 目前并没有提供类似查询 Mixer 当前是否处于 suspend 状态的 API。mixerSuspend/mixerResume 的返回值只能说明一次调用本身是否成功执行,但无法用于判断当前输出是否真的在正常工作。
我目前能想到的可尝试使用的一种确认方法就是:
做一个持续循环播放、音量拉到很小/静音的 Event,在游戏全程一直播放。
周期性调用 Studio::EventInstance::getTimelinePosition ,检查这个事件的时间轴是否在持续向前推进。
如果在游戏没有暂停、逻辑仍然在跑的前提下,这个事件的时间轴长时间停在同一个值不动,就可以认为 mixer已经不再正常工作。
一旦检测到这种情况,就可以执行你已经验证过有效的恢复逻辑: 先执行 mixerSuspend(),再执行 mixerResume()。
根据你前面提供的线索,确实有可能是 iOS 在极端低内存状态下出现了某种系统级行为:比方说底层音频输出单元被停止或中断,但没有触发标准的 AudioSession interruption 回调。由于 FMOD 在这种情况下无法收到通知,因此内部不会自动执行 suspend/resume,也无法感知输出实际已经停止。
在我们的 iOS 平台文档 中有提到,开发者可以自行监听 AVAudioSession 的 interruption 回调,并在合适的时机调用 mixerSuspend/mixerResume 进行控制。但这主要适用于“标准的音频中断”(例如电话、Siri、耳机插拔等),而你目前遇到的情况是否会触发这些回调,我目前还无法完全确定。
希望这些能给你提供到一些参考和帮助。
1 Like