UnityEditor crashes on EventInstance callback

Hello, IDK if this is the right place to ask, but I’m trying to make a class that plays in-game sfx using FMOD.Studio.EventInstance.

I store all the stopped instances in a stack, I push into the stack either when I’m creating a new Instance or inside OnEventInstanceStopped callback…

However the unity editor keeps crashing in OnEventInstanceStopped, I don’t get any logs out of the function so I believe it crashes when calling it?

public class AudioEventFXInstance
{
    private List<FMOD.Studio.EventInstance> instances = new List<FMOD.Studio.EventInstance>();
    private Stack<FMOD.Studio.EventInstance> stoppedInstances = new Stack<FMOD.Studio.EventInstance>();
    private IntPtr stackPtr;

    private Transform transform = null;
    private string path = "";

    public AudioEventFXInstance(Transform transform, string path)
    {
        this.transform = transform;
        this.path = path;

        stackPtr = GCHandle.ToIntPtr(GCHandle.Alloc(stoppedInstances));

        AddInstance();
    }

    ~AudioEventFXInstance()
    {
        foreach (FMOD.Studio.EventInstance instance in instances)
            instance.release();
    }

    private void AddInstance()
    {
        FMOD.Studio.EventInstance instance = FMODUnity.RuntimeManager.CreateInstance(path);
        instance.setCallback(OnEventInstanceStopped, FMOD.Studio.EVENT_CALLBACK_TYPE.STOPPED);
        instance.setUserData(stackPtr);

        instances.Add(instance);
        stoppedInstances.Push(instance);
    }

    private FMOD.RESULT OnEventInstanceStopped(FMOD.Studio.EVENT_CALLBACK_TYPE type, IntPtr _event, IntPtr parameters)
    {
        FMOD.Studio.EventInstance instance = new FMOD.Studio.EventInstance(_event);

        IntPtr data;
        instance.getUserData(out data);
        
        Stack<FMOD.Studio.EventInstance> stack = (GCHandle.FromIntPtr(data).Target as Stack<FMOD.Studio.EventInstance>);
        
        return FMOD.RESULT.OK;
    }

    public void Start()
    {
        FMOD.Studio.EventInstance instance;

        if (stoppedInstances.Count == 0)
            AddInstance();
            
        instance = stoppedInstances.Pop();

        FMODUnity.RuntimeManager.AttachInstanceToGameObject(instance, transform, (Rigidbody2D)null);
        instance.start();
    }
    
}

What versions of FMOD and Unity are you using?

When I try your script I do get:

UnityException: FindObjectsOfTypeAll is not allowed to be called from a MonoBehaviour constructor (or instance field initializer), call it in Awake or Start instead.

Which is due to the FMODUnity.RuntimeManager being called (and created) in the constructor, if the script is attached to a gameObject.

Are you able to get any meaningful info from the crash logs at all?

1 Like

Hello, Sorry for the late response, I’m unable to upload the crash log files here (Crash_2021-04-19_153046519.rar - Google Drive).

Unknown caused an Access Violation (0xc0000005)
in module Unknown at 0033:611109c1.

I’m using Unity 2019.4.22.f1 LTS release, I believe my FMOD version is 2.0.08, 64x, Build#114339.

Apologies for not providing the full source code, you can find the unity project here: GitHub - Light3039/Unity-Managers: A project with manager classes and tidy folder structure to start your 2d project with.
(Audio scripts are in Assets/Scripts/Audio/…)

You can crash the editor by spamming the 3 buttons in the middle, it crashes randomly when a sound stops.

I don’t get the UnityException you’ve mentioned, I think it’s because I use this class to create AudioEventFXInstance:
I’m not sure whether or not my appraoch is corerct.

public class AudioEmitterFX : MonoBehaviour
{
    [SerializeField] 
    private AudioEmitterData data; // struct that holds an array of string(fmod event)

    private Dictionary<string, AudioEventFXInstance> events = new Dictionary<string, AudioEventFXInstance>();

    private void Awake()
    {
        for (int i = 0; i < data.events.Length; i++)
        {
            events[data.events[i].Substring(data.events[i].LastIndexOf("/") + 1)] = new AudioEventFXInstance(transform, data.events[i]);
            Debug.Log(data.events[i] + " - > " + data.events[i].Substring(data.events[i].LastIndexOf("/") + 1));
        }
        Debug.Log(events);
    }

    public AudioEventFXInstance this[string name]
    {
        get { return events[name]; }
    }
}

This appears to be cause by the callback delegate being garbage collected, because it is not being cached the garbage collector will come along (at a seemingly random time) and it will appear to be unreferenced so it will be removed.

In general with callbacks, we recommend doing three things:

  • Cache the delegate, this will stop the garbage collector from removing the callback.

    (The next two are requirements for AOT compilers but we recommened doing them all the time as it does not hurt.)

  • Make callback functions static.

  • Functions require the [MonoPInvokeCallback] attribute.

This is mentioned in the Platform Specifics (callbacks on ahead of time compile platforms) section in our docs.

1 Like