System.unloadplugin(uint handle) not working


I’m creating a dsp using the system.loadplugin() (it is a .dll VST2 plugin)
I call after that createDSPPlugin().
Everything is working as expected.

When i call the system.unloadPlugin() it seems it does not unload it. I mean FMOD returns FMOD.RESULTS.OK but i can still access the handle with an external tool that communicates with the VST.

Is this a bug ?
Is there any other options to destroy a plugin handle ?

I need help ! It make crash the Unity Editor and my software because i need to destroy an recreate my FMOD system and reload the vst plugin. By doing that it spaw one instance of the vst each time i destroy and recreate the FMOD system !

I need to destroy the FMOD system because I need to go from RAW mode to automatic mode to be able to use 3d sounds positionning…

What version of FMOD are you using?

If you try to access the handle, through FMOD, after it has been unload you should get FMOD_ERR_PLUGIN_MISSING.

Hi Cameron !
I’m using FMOD Studio 2.00.04

when i destroy the System here is the code i execute before :

        if (0 != Handle)
            FMOD.RESULT result;
                result = CoreSystem.unloadPlugin(Handle);
            } while (result == FMOD.RESULT.ERR_DSP_INUSE);
            Debug.LogWarning("No handle so no need to clean it !");
        FMOD.RESULT test = CoreSystem.createDSPByPlugin(Handle, out FMOD.DSP dsp);

The last Debug.LogError says exactly what you expectec : FMOD_ERR_PLUGIN_MISSING .

That is expected. What is the issue?

Hi Cameron,

The issue is that the instance of the VST seams to continue to be active some how.
Any way i try to find a workaround.
Now i need to destroy it because i need to reset FMOD (destroy and create system again) to detect output changes. I’m trying to avoid to reset FMOD completly. This is the only part where i’ve not found a solution.

i’ve implemented the callbacks for that. It return all the time a FMOD.SYSTEM_CALLBACK_TYPE.RECORDLISTCHANGED but not very often the FMOD.SYSTEM_CALLBACK_TYPE.DEVICELISTCHANGED…

it seams that the recordlistchanged trigger because of the loopback of the outputs… and i need to detect both changes.

Is there a way to make FMOD detect DeviceListChanged and the Driver order to reset (to use with System.SetDriver()) ?

static FMOD.RESULT DevicesChangedCallback(IntPtr system, FMOD.SYSTEM_CALLBACK_TYPE type, IntPtr commanddata1, IntPtr commanddata2, IntPtr userdata)
            lock (callback_lock)
                if (userdata != IntPtr.Zero)
                    Debug.Log($"FMOD Devices has Changed {type}");
                    GCHandle objecthandle = GCHandle.FromIntPtr(userdata);
                    var manager = (objecthandle.Target as FMODCallBacksParameters);

                    switch (type)
                            manager.HS_OutputDevicesChanged = true;
                            manager.HS_InputDevicesChanged = true;

            return FMOD.RESULT.OK;

FInally, i’ve found a workaround. The callbacks seams not working properly.
Here is my solution to run in the FixedUpdate() in Unity :

public static bool CheckOutputListChange()
            result = FMODLowLevelSystems[ECanal.Canal1].getNumDrivers(out int NumDrivers);
            if (instance.DevicesName.Count == NumDrivers || !isFMODInit) return false;
            else return true;
public static bool CheckInputListChange()
                    result = FMODLowLevelSystems[ECanal.Canal1].getRecordNumDrivers(out _, out int NumConnected);
                    if (instance.RecordDevicesName.Count == NumConnected || !isFMODInit) return false;
                    else return true;

If you were to try to release a plugin while it is in use you will get an error (FMOD_ERR_DSP_INUSE), and if you try to use a plugin after it has been released you will get (FMOD_ERR_PLUGIN_MISSING). I’m not sure how it is still active. Are you able to send us a project that reproduces this?

FMOD.SYSTEM_CALLBACK_TYPE.DEVICELISTCHANGED should be doing this, otherwise that could be a bug.

Using FMOD_SYSTEM_CALLBACK_DEVICELISTCHANGED (Windows only) will disable any automated device ejection/insertion handling. Use this callback to control the behavior yourself.