Hi,
Thank you for sharing the information and code snippets.
It looks like you need to use Sound::getSyncPoint to fetch FMOD_SYNCPOINT and then query it with Sound::getSyncPointInfo.
Here is a modified version of your callback code that may resolve the issue:
[AOT.MonoPInvokeCallback(typeof(CHANNELCONTROL_CALLBACK))]
static RESULT ChannelStopCallback(IntPtr channelcontrol, CHANNELCONTROL_TYPE controltype, CHANNELCONTROL_CALLBACK_TYPE callbacktype, IntPtr commanddata1, IntPtr commanddata2)
{
if (callbacktype == FMOD.CHANNELCONTROL_CALLBACK_TYPE.SYNCPOINT)
{
// The "syncPointOffset" is always 0 and the other debug info is empty
/*sound.getSyncPointInfo(commanddata1, out var syncPointName, "StopPoint".Length, out var syncPointIndex, TIMEUNIT.MS);*/
/*sound.getSyncPointInfo(commanddata1, out var syncPointOffset, TIMEUNIT.MS);*/
/*Debug.LogWarning($"syncPointOffset: {syncPointOffset}, syncPointIndex: {syncPointIndex}, raw commanddata1: {commanddata1}");*/
// "[FMOD] assert : assertion: 'mUserCallbackThreadId == 0' failed" error occurs
/*channel.stop();*/
var newChannel = new FMOD.Channel(channelcontrol);
newChannel.setPaused(true); // Workaround. This is the only working way.
newChannel.getCurrentSound(out FMOD.Sound sound);
sound.getSyncPoint((int)commanddata1, out IntPtr syncpoint);
sound.getSyncPointInfo(syncpoint, out var syncPointName, "StopPoint".Length, out var syncPointOffset, TIMEUNIT.MS);
UnityEngine.Debug.LogWarning($"syncPointOffset: {syncPointOffset}, syncPointName: {syncPointName}");
}
return RESULT.OK;
}
Please note that as the callback method must be static, you’ll need to find alternative methods to manage data typically handled by instance variables.
I have managed to reproduce the error message you mentioned.
After discussing with the Dev team, the error you’re encountering likely occurs because attempting to stop a channel directly within a callback can lead to FMOD issuing another callback for the stop event, which is not permissible from within another callback. This is a safety measure to prevent potential recursive callbacks or other threading issues.
Your workaround using ChannelControl::setPaused is actually a legitimate and recommended approach under these circumstances.
Hope this helps, let me know if you have questions.