FMOD crashes Unity on scene change

Hi all :slight_smile:

I’m at my wits end here I’m afraid, really need help :frowning: I’ve done some FMOD before in C++, never had any issues, great middleware. However using it in Unity has been really difficult. I just can’t figure out how to deal with scene changes: when I change scene from a script Unity freezes and then crash. This doesn’t happen every time, but it happens enough to be a criticial issue. The stack trace (bottom) seems to suggest that FMOD is the culprit, and indeed when I remove all my FMOD listeners and emitters everything works fine with no crashes.

I need the soundscape to persist between scenes, so I use DontDestroyOnLoad on my listener object. However for testing I’ve put a listener in each scene, disabled by default. Another script on the same object activates it if it is the first on around:

	void Awake()
	{
		// There can only be one !
		if(__chosenOne == null)
		{
			// *I* am the milkman (my milk is delicious)
			__chosenOne = this;

			// Only ever have one FMOD_Listener active at a time!
			GetComponent<FMOD_Listener>().enabled = true;

			// This one should remain
			DontDestroyOnLoad(this.gameObject);
		}
		else
		{
			// Seppuku!
			Destroy(this.gameObject);
		}
	}

This isn’t working though: it breaks the sound, I get null-reference and/or “the requested event, bus or vca was not found” errors. My previous version didn’t break the sound, but didn’t stop the crash either:

	void OnEnable()
	{
		// There can only be one !
		foreach(SympathyFMOD_Listener other in FindObjectsOfType(typeof(SympathyFMOD_Listener)))
			if(other != this)
				Destroy(other.gameObject);

		// This one should remain
		DontDestroyOnLoad(gameObject);
	}

So basically my choice right now, and this is after months of development and due-dates being pushed back, is between no sound or a high probability of the application crashing whenever I change scenes. Please help :o

I’m using a version of the plugin from late last-year when development started.

========== OUTPUTING STACK TRACE ==================

(0x6B64137C) (fmodstudio): (filename not available): FMOD_Studio_EventInstance_GetPlaybackState + 0x1c
(0x0AE85039) (Mono JIT code): (filename not available):  (wrapper managed-to-native) FMOD.Studio.EventInstance:FMOD_Studio_EventInstance_GetPlaybackState (intptr,FMOD.Studio.PLAYBACK_STATE&) + 0x69 (0AE84FD0 0AE8509B) [05846BD0 - Unity Child Domain] + 0x0
(0x0AE84FB3) (Mono JIT code): (filename not available):  FMOD.Studio.EventInstance:getPlaybackState (FMOD.Studio.PLAYBACK_STATE&) + 0x2b (0AE84F88 0AE84FBE) [05846BD0 - Unity Child Domain] + 0x0
(0x0AE84F2F) (Mono JIT code): (filename not available):  FMOD_StudioEventEmitter:getPlaybackState () + 0x9f (0AE84E90 0AE84F77) [05846BD0 - Unity Child Domain] + 0x0
(0x0AE84D8F) (Mono JIT code): (filename not available):  FMOD_StudioEventEmitter:OnDestroy () + 0x8f (0AE84D00 0AE84E67) [05846BD0 - Unity Child Domain] + 0x0
(0x0904BE1F) (Mono JIT code): (filename not available):  (wrapper runtime-invoke) object:runtime_invoke_void__this__ (object,intptr,intptr,intptr) + 0x8f (0904BD90 0904BEEA) [05846BD0 - Unity Child Domain] + 0x0
(0x09E0FEDE) c:\buildslave\monoandruntimeclasslibs\build\mono\mini\mini.c (4889 + 0xc): mono_jit_runtime_invoke + 0x214
(0x09D7D680) c:\buildslave\monoandruntimeclasslibs\build\mono\metadata\object.c (2618 + 0x10): mono_runtime_invoke + 0x51
(0x00706EF8) c:\buildagent\work\d3d49558e4d408f4\runtime\scripting\backend\mono\scriptingbackendapi_mono.cpp (183 + 0x1a): scripting_method_invoke + 0xb8
(0x00826C78) c:\buildagent\work\d3d49558e4d408f4\runtime\scripting\backend\scriptinginvocation.cpp (115 + 0x0): ScriptingInvocation::Invoke + 0x58
(0x0082716E) c:\buildagent\work\d3d49558e4d408f4\runtime\scripting\backend\scriptinginvocation.cpp (99 + 0x0): ScriptingInvocation::Invoke + 0xe
(0x008271DC) c:\buildagent\work\d3d49558e4d408f4\runtime\scripting\backend\scriptinginvocationnoargs.cpp (120 + 0x13): ScriptingInvocationNoArgs::InvokeChecked + 0x2c
(0x006F2300) c:\buildagent\work\d3d49558e4d408f4\runtime\mono\monobehaviour.cpp (347 + 0x0): MonoBehaviour::CallMethodInactive + 0xa0
(0x006F2811) c:\buildagent\work\d3d49558e4d408f4\runtime\mono\monobehaviour.cpp (294 + 0x0): MonoBehaviour::WillDestroyComponent + 0xb1
(0x007D2777) c:\buildagent\work\d3d49558e4d408f4\runtime\misc\gameobjectutility.cpp (990 + 0x0): PreDestroyRecursive + 0x67
(0x007D2824) c:\buildagent\work\d3d49558e4d408f4\runtime\misc\gameobjectutility.cpp (998 + 0x40): PreDestroyRecursive + 0x114
(0x007D2824) c:\buildagent\work\d3d49558e4d408f4\runtime\misc\gameobjectutility.cpp (998 + 0x40): PreDestroyRecursive + 0x114
(0x007D2C24) c:\buildagent\work\d3d49558e4d408f4\runtime\misc\gameobjectutility.cpp (1054 + 0x11): DestroyGameObjectHierarchy + 0x24
(0x007D328D) c:\buildagent\work\d3d49558e4d408f4\runtime\misc\gameobjectutility.cpp (1200 + 0x6): DestroyObjectHighLevel + 0x4fd
(0x0081855E) c:\buildagent\work\d3d49558e4d408f4\runtime\misc\sceneunloading.cpp (40 + 0x7): UnloadGameScene + 0x11e
(0x007DE7D4) c:\buildagent\work\d3d49558e4d408f4\runtime\misc\player.cpp (1330 + 0x0): LevelLoading::LoadLevel + 0x264
(0x007DEA29) c:\buildagent\work\d3d49558e4d408f4\runtime\misc\player.cpp (372 + 0x0): PlayerLoadLevelFromThread + 0x19
(0x007DF389) c:\buildagent\work\d3d49558e4d408f4\runtime\misc\preloadmanager.cpp (780 + 0x0): PreloadLevelOperation::IntegrateMainThread + 0xc9
(0x007E0F04) c:\buildagent\work\d3d49558e4d408f4\runtime\misc\preloadmanager.cpp (471 + 0x0): PreloadManager::UpdatePreloadingSingleStep + 0x134
(0x007E1160) c:\buildagent\work\d3d49558e4d408f4\runtime\misc\preloadmanager.cpp (534 + 0x0): PreloadManager::WaitForAllAsyncOperationsToComplete + 0x50
(0x007E1239) c:\buildagent\work\d3d49558e4d408f4\runtime\misc\preloadmanager.cpp (564 + 0x0): PreloadManager::UpdatePreloading + 0x99
(0x007DD577) c:\buildagent\work\d3d49558e4d408f4\runtime\misc\player.cpp (1771 + 0x0): PlayerLoop + 0x197
(0x00F654FC) c:\buildagent\work\d3d49558e4d408f4\editor\src\application.cpp (2286 + 0xb): Application::UpdateScene + 0x21c
(0x00F69577) c:\buildagent\work\d3d49558e4d408f4\editor\src\application.cpp (2216 + 0x0): Application::UpdateSceneIfNeeded + 0x37
(0x0100C682) c:\buildagent\work\d3d49558e4d408f4\editor\platform\windows\wineditormain.cpp (336 + 0x0): MainMessageLoop + 0x1c2
(0x0100D5C7) c:\buildagent\work\d3d49558e4d408f4\editor\platform\windows\wineditormain.cpp (848 + 0x0): WinMain + 0xe37
(0x01125C34) f:\dd\vctools\crt_bld\self_x86\crt\src\crt0.c (275 + 0x1c): __tmainCRTStartup + 0x11a
(0x7606336A) (kernel32): (filename not available): BaseThreadInitThunk + 0x12
(0x77C29F72) (ntdll): (filename not available): RtlInitializeExceptionChain + 0x63
(0x77C29F45) (ntdll): (filename not available): RtlInitializeExceptionChain + 0x36

========== END OF STACKTRACE ===========

Whoa, talk about rubber-duck debugging.

I had a thought just after writing this all out clearly: it’s not the listeners I need to be worried about it’s the sound system itself. I put a breakpoint to check when the pointer to the sound system was being changed and realised that the FMOD_SoundSystem::OnDisable() resets this to 0. That means that when the emitter show up to play it’s event at the start of the next scene it finds the system uninitialised, and since the listener persists it doesn’t reinitialise anything.

The way I solved the problem was therefore to force the “FMOD_SoundSystem” game object to persist as well, so its rawPtr is not reset to NULL in between scenes. Now I have my cake and can eat it too :smiley:

Code:

using UnityEngine;
using System.Collections;

public class SympathyFMOD_Listener : MonoBehaviour 
{
	private static SympathyFMOD_Listener __chosenOne = null;

	void Awake()
	{
		// There can only be one !
		if(__chosenOne == null)
		{
			Debug.Log ("SympathyFMOD_Listener " + this.GetInstanceID() + " is the singleton");
			// *I* am the milkman (my milk is delicious)
			__chosenOne = this;
			
			// Only ever have one FMOD_Listener active at a time!
			GetComponent<FMOD_Listener>().enabled = true;
			
			// This one should remain
			DontDestroyOnLoad(this.gameObject);
		}
		else
		{
			Debug.Log ("SympathyFMOD_Listener " + this.GetInstanceID() + "  will self-destruct");
			// Seppuku!
			Destroy(this.gameObject);
		}
	}

	void Start()
	{
		if(__chosenOne == this)
		{
			// FMOD studio system should not be destroyed either
			DontDestroyOnLoad(GameObject.Find("FMOD_StudioSystem"));
		}
	}
	
	void Update ()
	{
		transform.position = Camera.main.transform.position;
	}
}

Hey, thanks very much. We have been intermittently plagued with this same issue, and were able to fix it last night just in time for a demo, thanks to you!

Thank you!!!

I remembered briefly reading this post, then ran into the same problem in my current project. Added this and now it works like a charm! :smiley:

Cheers!!