RuntimeManager ERROR when loading another scene: "[FMOD] Attempted access by script to RuntimeManager while application is quitting"


#1

Yesterday I decided to try the Fmod Unity Timeline Integration. I re-exported the banks and created a new Fmod Event Track and linked it to a newly created event.

Right after that, when I run the game in the Editor, I’ve been getting an Exception from the RuntimeManager.cs the moment I unload the current scene and load a new one(it does NOT happen if I reload the current scene or when I first load the initial scenes):

Exception: [FMOD] Attempted access by script to RuntimeManager while application is quitting
FMODUnity.RuntimeManager.get_Instance () (at Assets/Plugins/FMOD/RuntimeManager.cs:52)
FMODUnity.RuntimeManager.SetListenerLocation (Int32 listenerIndex, UnityEngine.GameObject gameObject, UnityEngine.Rigidbody2D rigidBody2D) (at Assets/Plugins/FMOD/RuntimeManager.cs:957)
FMODUnity.StudioListener.SetListenerLocation () (at Assets/Plugins/FMOD/StudioListener.cs:42)
FMODUnity.StudioListener.Update () (at Assets/Plugins/FMOD/StudioListener.cs:31)

After a full day of pulling my hair out, I’m starting to wonder if maybe I did some obscure change that created this issue…

The error log doesn’t point to any specific code, so I’m assuming it’s due to some entities being unloaded (btw, is there a way to have a more detailed error log?).
When I click on the actual error in Unity it highlights my AudioListener GameObject (that is instanced in a Scene that doesn’t get destroyed on load) and contains the StudioListener.cs.

Also going through the code just before the error, I can see that the function that triggers it is from the StudioListener.cs when doing:

void Update()
{
    SetListenerLocation();
}

And I can see that the error in the RuntimeManager.cs is because the isQuitting flag is being set to true right after the SetListenerLocation is called:

void OnDestroy()
{
    if (studioSystem.isValid())
    {
        studioSystem.release();
        studioSystem.clearHandle();
    }
    initException = null;
    instance = null;
    isQuitting = true;
}

Is the problem because the RuntimeManager no longer exists and was destroyed? Is that the expected behavior on level load? (Is there only one instance of the RuntimeManager per game?)

Is it the StudioListener that should not be calling the RuntimeManager during level load and it should be disabled?

Is it some entity that didn’t get destroyed properly? How can I track it?

Any help would be VERY appreciated.

Thanks.


#2

So after going through revision control and every code change I was able to realize that it was actually some added code, by FMOD, to a Unity scene.
For some reason, when I implemented the timeline, FMOD added TWO blocks of code to my Unity scene (I was getting the error twice). Here is one of them:

--- !u!1 &1830785508
GameObject:
  m_ObjectHideFlags: 1
  m_CorrespondingSourceObject: {fileID: 0}
  m_PrefabInternal: {fileID: 0}
  serializedVersion: 6
  m_Component:
  - component: {fileID: 1830785510}
  - component: {fileID: 1830785509}
  m_Layer: 0
  m_Name: FMOD.UnityIntegration.RuntimeManager
  m_TagString: Untagged
  m_Icon: {fileID: 0}
  m_NavMeshLayer: 0
  m_StaticEditorFlags: 0
  m_IsActive: 1
--- !u!114 &1830785509
MonoBehaviour:
  m_ObjectHideFlags: 1
  m_CorrespondingSourceObject: {fileID: 0}
  m_PrefabInternal: {fileID: 0}
  m_GameObject: {fileID: 1830785508}
  m_Enabled: 1
  m_EditorHideFlags: 0
  m_Script: {fileID: 11500000, guid: 5e5fb8ce07f0ce84b9d1852869527ea5, type: 3}
  m_Name: 
  m_EditorClassIdentifier: 
  fmodPlatform: 1
  cachedPointers: 00000000000000000000000000000000
--- !u!4 &1830785510
Transform:
  m_ObjectHideFlags: 1
  m_CorrespondingSourceObject: {fileID: 0}
  m_PrefabInternal: {fileID: 0}
  m_GameObject: {fileID: 1830785508}
  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
  m_LocalPosition: {x: 0, y: 0, z: 0}
  m_LocalScale: {x: 1, y: 1, z: 1}
  m_Children: []
  m_Father: {fileID: 0}
  m_RootOrder: 37
  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}

It seems like a hidden RuntimeManager GameObject, probably generated when I was trying to implement the Fmod Unity timeline stuff…after deleting these TWO blocks of text from the scene, it all works.

Now what I’m worried is, how did this happen? And how can I see these hidden GameObjects, in the engine, so I can remove them next time it happens?


#3

Thank you for reporting this.

When auditioning the Timeline in editor, a RuntimeManager is created to play the events, this is normally hidden and cleaned up automatically. Although it appears that it is able to be saved to the scene.

We are currently working on resolving this for an upcoming release.


#4

We are running into this as well.
It seems almost as if this gets created with playables/directors as well, and also, not cleaned up.

Not a disaster once you know it happens, and it is easily cleaned up, but still good to fix this.

This is our scene after doing layout with various directors in scene:


FMOD Memory Leak with Unity
#5

@houseofsecrets what is that “Hidden Objects Viewer”? Is that a Unity plugin?
It seems super useful. I had to read the text version of the scene and was lucky to find the Runtime Manager


#6

Having the same problem right now. How to fix it.

PS: Nvm for now i just comment out this in RuntimeManager.cs and it helped:-

    if (isQuitting)
            {
                //throw new Exception("[FMOD] Attempted access by script to RuntimeManager while application is quitting");
            }

#7

That’s not going to fix it, that’s just hiding the problem and will bite you in the rear when sound events get registered at certain points in your code when using multiple scenes (or additive loads.)

The best way the get rid of it during build is to run your scenes through a build processor

In our current project for example:

using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEngine;
using System.Collections.Generic;

public class RacerPreBuild : IProcessSceneWithReport
{
    public int callbackOrder { get { return 0; } }
    public void OnProcessScene(UnityEngine.SceneManagement.Scene scene, BuildReport report)
    {
        if (EditorApplication.isPlaying) return;

        Debug.Log("BuildProcessorScenes.OnProcessScene " + scene.name);
        
        // Remove FMOD runtime crap
        Stack<GameObject> HiddenObjects = new Stack<GameObject>();
        var allObjects = GameObject.FindObjectsOfType<GameObject>();
        foreach (var go in allObjects)
        {
            if ((go.hideFlags & HideFlags.HideInHierarchy) != 0)
            {
                if (go.GetComponent<FMODUnity.RuntimeManager>() != null)
                {
                    HiddenObjects.Push(go);
                    Debug.Log($"Adding {go.name} to list for destruction");
                }
            }
        }

        while (HiddenObjects.Count > 0)
        {
            GameObject.DestroyImmediate(HiddenObjects.Pop());
        }
    }
}

#8

@houseofsecrets @blackeel

None of those are actually fixing the problem, but just hiding it, or delaying it. You will still run into issues during Editor work with your solution @houseofsecrets.

The cleanest way to deal with this is to REMOVE the hidden objects that were created by FMOD from your scene.
The way I’m doing it is by editing the actual scene file.

To do so, your scenes (and this is SUPER helpful for a lot of similar problems you run into when working with Unity) is to convert your scene files from Binary to Text-Based. This will not only allow you to have much lighter version control revisions, but you can actually read and compare changes in your scene between previous revisions.

You can learn how to do that here (under the Asset Serialization section):
https://docs.unity3d.com/Manual/class-EditorManager.html

Once you’ve done that, you can now open your scenes with any text editor, and see the properties of all the instanced objects, hidden or not!
In the case of the issue we are talking about, just look for any gameObject that is instancing the RuntimeManager, searching for this line:

 m_Name: FMOD.UnityIntegration.RuntimeManager

And then make sure to delete the WHOLE entity that contains that m_Name
They start with a line similar to this:

--- !u!1 &amp;1830785508

and the last line is the LocalEulerAnglesHint:

m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}

So in my case, I had 2 versions similar to that. You can see it in my first post and a gameObject is described in a text-based version of the scene.

P.S. Changing your Unity scenes from Binary to Text-Based is highly recommended. I’ve had several similar issues, and this is the only way to clearly see what your scene is composed of.


#9

That’s what our script allows us to do (the hidden object viewer), without the chance a designer screws up a scene beyond repair, where the only repair often is reverting back through svn.

The build processor simply removes it during build, as the runtime scripts sometimes get created during building as well (as far as I can tell)

But, yes, having your scenes as text should be (or is these days) the default, for a plethora of reasons.


#10

Any chance you could share that hidden object viewer script?


#11

Sure, I can’t take credit for it, it was plucked from somewhere else and modified a bit.
Just save into a Editor folder.

using UnityEngine;
using UnityEditor;
using UnityEditor.SceneManagement;
using System.Collections.Generic;

public class HiddenObjectsViewer : EditorWindow
{
    [MenuItem("House of Secrets/Hidden Objects Viewer")]
    public static void ShowWindow()
    {
        var window = GetWindow<HiddenObjectsViewer>();
        window.titleContent = new GUIContent("Hidden Objects Viewer");
        window.GatherHiddenObjects();
    }

    #region GUI

    private static readonly GUILayoutOption ButtonWidth = GUILayout.Width(80);
    private static readonly GUILayoutOption BigButtonHeight = GUILayout.Height(35);

    private void OnGUI()
    {
        GUILayout.BeginHorizontal();
        {
            if (GUILayout.Button("Refresh"))
            {
                GatherHiddenObjects();
            }
        }
        GUILayout.EndHorizontal();
        bool odd = false;
        EditorGUILayout.LabelField("Hidden Objects (" + HiddenObjects.Count + ")", (GUIStyle)"ProjectBrowserHeaderBgMiddle");
        scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
        for (int i = 0; i < HiddenObjects.Count; i++)
        {
            var hiddenObject = HiddenObjects[i];
            GUILayout.BeginHorizontal();
            {
                var gone = hiddenObject == null;
                GUILayout.Label(gone ? "null" : hiddenObject.name, (odd ? (GUIStyle)"ObjectPickerResultsOdd" : (GUIStyle)"ObjectPickerResultsEven"), GUILayout.ExpandWidth(true));
                odd = !odd;
                if (gone)
                {
                    GUILayout.Box("Select", ButtonWidth);
                    GUILayout.Box("Show", ButtonWidth);
                    GUILayout.Box("Delete", ButtonWidth);
                }
                else
                {
                    if (GUILayout.Button("Select", (GUIStyle)"sv_label_1", ButtonWidth))
                    {
                        Selection.activeGameObject = hiddenObject;
                    }
                    if (GUILayout.Button(IsHidden(hiddenObject) ? "Show" : "Hide", IsHidden(hiddenObject) ? (GUIStyle)"sv_label_0" : (GUIStyle)"sv_label_3", ButtonWidth))
                    {
                        hiddenObject.hideFlags ^= HideFlags.HideInHierarchy;
                        EditorSceneManager.MarkSceneDirty(hiddenObject.scene);
                    }
                    if (GUILayout.Button("Delete", (GUIStyle)"sv_label_5", ButtonWidth))
                    {
                        var scene = hiddenObject.scene;
                        DestroyImmediate(hiddenObject);
                        EditorSceneManager.MarkSceneDirty(scene);
                        GatherHiddenObjects();
                    }
                }
            }
            GUILayout.EndHorizontal();
        }
        EditorGUILayout.EndScrollView();
    }

    #endregion

    #region Hidden Objects

    private List<GameObject> HiddenObjects = new List<GameObject>();
    private Vector2 scrollPos;

    private void GatherHiddenObjects()
    {
        HiddenObjects.Clear();

        var allObjects = FindObjectsOfType<GameObject>();
        foreach (var go in allObjects)
        {
            if ((go.hideFlags & HideFlags.HideInHierarchy) != 0)
            {
                HiddenObjects.Add(go);
            }
        }

        Repaint();
    }

    private static bool IsHidden(GameObject go)
    {
        return (go.hideFlags & HideFlags.HideInHierarchy) != 0;
    }

    #endregion
}

#12

We were running into this, along deleting all the created instanced, we’ve modified RuntimeManager to not save the instance in scenes and that seems to have fixed it for us.

Open RuntimeManager.cs and find

gameObject.hideFlags = HideFlags.HideInHierarchy;

Replace it with

gameObject.hideFlags = HideFlags.HideAndDontSave;

Let us know if anyone finds that this breaks something.