c# List of Managers is empty in build, works fine in editor

I’m using Unity 3D (2018.2.1f1) for a VR film project using 360 video. There are several “scenes” in the movie and each one has a SoundManager associated with it. I have an object, SoundOverlord, which keeps track of these SoundManagers and makes sure they get activated when their scene starts and deactivated when the scene ends. (Note that there is only one Unity scene, when I say “scene” I’m referring to scenes in the film). The SoundOverlord contains a public List - managers - of SoundManagers which I populated in the Inspector.

When I run the project in the Unity Editor, everything works fine - the SoundOverlord is able to activate the first SoundManager right away, and then switch to the second when the second scene starts, and so on.
But when I build and run it, any time it tries to access an item from the List, I get an ArgumentOutOfRangeException. I printed managers.Count to the Debug.Log, in editor it prints 6 (as it should), in build it prints 0.

public class SoundOverlord : MonoBehaviourSingleton<SoundOverlord> 
{

public List<SoundManagerScript> managers = new List<SoundManagerScript>();

public int currentSceneIndex = 0;

public SoundManagerScript GetCurrentSoundManager()
{
    Debug.Log("There are " + managers.Count + " SoundManagers in this list");
    return managers[currentSceneIndex]; // ERROR HERE
}
}

The error occurs whenever GetCurrentSoundManager() is called, at “return managers[0]”.
I’ve been struggling with this problem for 4 days, if anyone can help I would be so grateful.

"SoundOverlord contains a public List - managers - of SoundManagers which I populated in the Inspector. "

Try allocating them in code instead, and don’t rely on the inspector for that.

Your problem most likely is related to how your “MonoBehaviourSingleton” is implemented and may be related to the execution order.

Note that there are many really bad MonoBheaviour based singleton implementations out there which includes the one on the wiki. I wouldn’t recommend using the current implementation. The lock is pointless as everything in the code is bound to the main thread and can not be used from another thread. The applying of DontDestroyOnLoad is not consistent. The worst thing however is that the lock is always applied each time you access the instance which is just bad practise in general.

There are generally 3 different types of singetons you may want to use in Unity:

  • Actual singletons which are not derived from MonoBehaviour. Those would look way different than MonoBehaviour based singetons.
  • Serialized MonoBehaviour based singleton
  • Non serialized MonoBehaviour based singleton

Nonserialized monobehaviour singletons may be used for things like tween libraries, coroutine host object and things like that which require that you have an actual MonoBehaviour instance but it may be created lazily.

For the serialized version it doesn’t make much sense to create an instance on the fly since the main point is to provide serialized data. Such a singleton could either be located in the scene and found by FindObjectOfType or loaded from serialized data. This could be another dedicated loading scene or a prefab which you could instantiate. However if the manager should hold references to other objects in the scene there is only one way.

We need to see how your singleton is implemented. You most likely call “GetCurrentSoundManager” before the singleton is deserialized / loaded. Another possibility is that “currentSceneIndex” is also serialized to an invalid index.