一直在使用 FMOD 进行 C# 游戏开发,但我很早就遇到了一个似乎无法解决的问题.我想做一些分支音频的东西并将一些游戏动作同步到节拍等,所以我尝试将同步点添加到我的音乐曲目中.代码如下:
Been messing around with FMOD for C# game development and I've hit a snag early on that I can't seem to get around. I want to do some branching audio stuff and sync some gameplay action to beats and such, so I've tried adding syncpoints to my music tracks. Here's code:
public class Music
{
private Sound music;
private Channel channel;
private IntPtr syncPtr;
public string File { get; private set; }
public Music(string file)
{
File = file;
}
public void Load()
{
music = new Sound();
Audio.System.createSound(File, MODE.HARDWARE, ref music);
}
public void Unload()
{
music.release();
}
public virtual void Play()
{
Audio.System.playSound(channel == null ? CHANNELINDEX.FREE : CHANNELINDEX.REUSE, music, false, ref channel);
music.addSyncPoint(500, TIMEUNIT.MS, "wooo", ref syncPtr);
channel.setCallback(channelCallback);
}
private RESULT channelCallback(IntPtr channelraw, CHANNEL_CALLBACKTYPE type, IntPtr commanddata1, IntPtr commanddata2)
{
if (type == CHANNEL_CALLBACKTYPE.SYNCPOINT)
Console.WriteLine("sync!");
return RESULT.OK;
}
}
然后……
m = new Music(MUS_TUTORIAL); //m is static
m.Load();
m.Play();
歌曲加载并播放良好...直到它达到我添加的 500 毫秒同步点.此时,VC# 从 FMOD.EventSystem.update() 中吐出以下错误:
The song loads and plays fine... until it hits that 500ms syncpoint I added. At this point, VC# spits out the following error from within FMOD.EventSystem.update():
对类型为垃圾收集的委托进行了回调'游戏!FMOD.CHANNEL_CALLBACK::Invoke'.这可能会导致应用程序崩溃、损坏和数据丢失.将委托传递给非托管代码时,它们必须由托管应用程序,直到保证它们永远不会被调用.
A callback was made on a garbage collected delegate of type 'Game!FMOD.CHANNEL_CALLBACK::Invoke'. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.
所以不知何故,FMOD 正在丢失我通过它的委托.保存委托的 Music 实例尚未被垃圾收集 - 我现在将它存储在静态变量中 - 但我也尝试过使用静态方法无济于事.如果我禁用 CallbackOnCollectedDelegate MDA,则错误将变为空引用异常,因此 MDA 没有弄错.我想我一定不能完全理解 FMOD 在这里做什么.
So somehow FMOD is losing track of the delegate I passed it. The Music instance that holds the delegate has not been garbage collected - I'm storing it in a static variable for now - but I've tried with a static method too to no avail. If I disable the CallbackOnCollectedDelegate MDA the error becomes a null reference exception, so the MDA isn't mistaken. I assume I must just not fully understand what FMOD is doing here.
是否有任何 C# + FMOD 大师能够看到我的错误?
Are any C# + FMOD gurus able to see my mistake?
channel.setCallback(channelCallback);
这就是问题陈述.FMod 是非托管代码.您在此处创建一个委托对象并将其传递给非托管代码.问题是,垃圾收集器无法跟踪本机代码持有的引用.下一次垃圾回收将找到对象的 no 引用并收集它.当本机代码进行回调时 Kaboom.
That's the problem statement. FMod is unmanaged code. You are creating a delegate object here and passing it to the unmanaged code. Problem is, the garbage collector cannot track references held by native code. The next garbage collection will find no references to the object and collect it. Kaboom when the native code makes the callback.
您需要自己保留参考资料,以免发生这种情况:
You need to keep a reference yourself so this won't happen:
public class Music
{
private SomeDelegateType callback
//...
public Music(string file)
{
File = file;
callback = new SomeDelegateType(channelCallback);
}
public virtual void Play()
{
Audio.System.playSound(channel == null ? CHANNELINDEX.FREE : CHANNELINDEX.REUSE, music, false, ref channel);
music.addSyncPoint(500, TIMEUNIT.MS, "wooo", ref syncPtr);
channel.setCallback(callback);
}
您需要从 FMod 包装器代码中找到实际的委托类型,我只是猜测SomeDelegateType".
You need to find the actual delegate type from the FMod wrapper code, I merely guessed at "SomeDelegateType".
这篇关于正在收集回调代表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!